diff options
author | Seivan Heidari <[email protected]> | 2019-11-04 23:00:30 +0000 |
---|---|---|
committer | Seivan Heidari <[email protected]> | 2019-11-04 23:00:30 +0000 |
commit | 8eb5148af7e7a87a685f7581809368b13eaa17ec (patch) | |
tree | 7f0ac4da3fa6e487fe1692a041d4d1144fd3d8db /crates/ra_hir | |
parent | c60f9bf4c6d6ddd341c673b228b6aa1add3da62b (diff) | |
parent | 38f2bd21fbecf1c997a4ab9a8913e8b5487088e3 (diff) |
Merge branch 'master' into feature/themes
Diffstat (limited to 'crates/ra_hir')
-rw-r--r-- | crates/ra_hir/src/code_model.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir/src/db.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir/src/expr/scope.rs | 8 | ||||
-rw-r--r-- | crates/ra_hir/src/lib.rs | 9 | ||||
-rw-r--r-- | crates/ra_hir/src/mock.rs | 262 | ||||
-rw-r--r-- | crates/ra_hir/src/test_db.rs | 120 | ||||
-rw-r--r-- | crates/ra_hir/src/ty.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/infer/expr.rs | 6 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/infer/path.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/lower.rs | 15 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 32 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/traits/chalk.rs | 7 |
12 files changed, 171 insertions, 302 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 181c5d47a..4e273d9e4 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs | |||
@@ -30,8 +30,8 @@ use crate::{ | |||
30 | impl_block::ImplBlock, | 30 | impl_block::ImplBlock, |
31 | resolve::{Resolver, Scope, TypeNs}, | 31 | resolve::{Resolver, Scope, TypeNs}, |
32 | traits::TraitData, | 32 | traits::TraitData, |
33 | ty::{InferenceResult, TraitRef}, | 33 | ty::{InferenceResult, Namespace, TraitRef}, |
34 | Either, HasSource, Name, ScopeDef, Ty, {ImportId, Namespace}, | 34 | Either, HasSource, ImportId, Name, ScopeDef, Ty, |
35 | }; | 35 | }; |
36 | 36 | ||
37 | /// hir::Crate describes a single crate. It's the main interface with which | 37 | /// hir::Crate describes a single crate. It's the main interface with which |
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index eb66325f7..11b3f94ae 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs | |||
@@ -14,10 +14,10 @@ use crate::{ | |||
14 | traits::TraitData, | 14 | traits::TraitData, |
15 | ty::{ | 15 | ty::{ |
16 | method_resolution::CrateImplBlocks, traits::Impl, CallableDef, FnSig, GenericPredicate, | 16 | method_resolution::CrateImplBlocks, traits::Impl, CallableDef, FnSig, GenericPredicate, |
17 | InferenceResult, Substs, Ty, TypableDef, TypeCtor, | 17 | InferenceResult, Namespace, Substs, Ty, TypableDef, TypeCtor, |
18 | }, | 18 | }, |
19 | type_alias::TypeAliasData, | 19 | type_alias::TypeAliasData, |
20 | Const, ConstData, Crate, DefWithBody, ExprScopes, FnData, Function, Module, Namespace, Static, | 20 | Const, ConstData, Crate, DefWithBody, ExprScopes, FnData, Function, Module, Static, |
21 | StructField, Trait, TypeAlias, | 21 | StructField, Trait, TypeAlias, |
22 | }; | 22 | }; |
23 | 23 | ||
diff --git a/crates/ra_hir/src/expr/scope.rs b/crates/ra_hir/src/expr/scope.rs index 5496822e7..c14c2ab66 100644 --- a/crates/ra_hir/src/expr/scope.rs +++ b/crates/ra_hir/src/expr/scope.rs | |||
@@ -174,11 +174,11 @@ fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope | |||
174 | 174 | ||
175 | #[cfg(test)] | 175 | #[cfg(test)] |
176 | mod tests { | 176 | mod tests { |
177 | use ra_db::SourceDatabase; | 177 | use ra_db::{fixture::WithFixture, SourceDatabase}; |
178 | use ra_syntax::{algo::find_node_at_offset, ast, AstNode}; | 178 | use ra_syntax::{algo::find_node_at_offset, ast, AstNode}; |
179 | use test_utils::{assert_eq_text, extract_offset}; | 179 | use test_utils::{assert_eq_text, extract_offset}; |
180 | 180 | ||
181 | use crate::{mock::MockDatabase, source_binder::SourceAnalyzer}; | 181 | use crate::{source_binder::SourceAnalyzer, test_db::TestDB}; |
182 | 182 | ||
183 | fn do_check(code: &str, expected: &[&str]) { | 183 | fn do_check(code: &str, expected: &[&str]) { |
184 | let (off, code) = extract_offset(code); | 184 | let (off, code) = extract_offset(code); |
@@ -191,7 +191,7 @@ mod tests { | |||
191 | buf | 191 | buf |
192 | }; | 192 | }; |
193 | 193 | ||
194 | let (db, _source_root, file_id) = MockDatabase::with_single_file(&code); | 194 | let (db, file_id) = TestDB::with_single_file(&code); |
195 | let file = db.parse(file_id).ok().unwrap(); | 195 | let file = db.parse(file_id).ok().unwrap(); |
196 | let marker: ast::PathExpr = find_node_at_offset(file.syntax(), off).unwrap(); | 196 | let marker: ast::PathExpr = find_node_at_offset(file.syntax(), off).unwrap(); |
197 | let analyzer = SourceAnalyzer::new(&db, file_id, marker.syntax(), None); | 197 | let analyzer = SourceAnalyzer::new(&db, file_id, marker.syntax(), None); |
@@ -288,7 +288,7 @@ mod tests { | |||
288 | fn do_check_local_name(code: &str, expected_offset: u32) { | 288 | fn do_check_local_name(code: &str, expected_offset: u32) { |
289 | let (off, code) = extract_offset(code); | 289 | let (off, code) = extract_offset(code); |
290 | 290 | ||
291 | let (db, _source_root, file_id) = MockDatabase::with_single_file(&code); | 291 | let (db, file_id) = TestDB::with_single_file(&code); |
292 | let file = db.parse(file_id).ok().unwrap(); | 292 | let file = db.parse(file_id).ok().unwrap(); |
293 | let expected_name = find_node_at_offset::<ast::Name>(file.syntax(), expected_offset.into()) | 293 | let expected_name = find_node_at_offset::<ast::Name>(file.syntax(), expected_offset.into()) |
294 | .expect("failed to find a name at the target offset"); | 294 | .expect("failed to find a name at the target offset"); |
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 3ba99d92d..5f2a05e76 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs | |||
@@ -29,8 +29,6 @@ macro_rules! impl_froms { | |||
29 | pub mod debug; | 29 | pub mod debug; |
30 | 30 | ||
31 | pub mod db; | 31 | pub mod db; |
32 | #[macro_use] | ||
33 | pub mod mock; | ||
34 | pub mod source_binder; | 32 | pub mod source_binder; |
35 | 33 | ||
36 | mod ids; | 34 | mod ids; |
@@ -52,6 +50,8 @@ mod code_model; | |||
52 | pub mod from_source; | 50 | pub mod from_source; |
53 | 51 | ||
54 | #[cfg(test)] | 52 | #[cfg(test)] |
53 | mod test_db; | ||
54 | #[cfg(test)] | ||
55 | mod marks; | 55 | mod marks; |
56 | 56 | ||
57 | use hir_expand::AstId; | 57 | use hir_expand::AstId; |
@@ -81,10 +81,7 @@ pub use crate::{ | |||
81 | 81 | ||
82 | pub use hir_def::{ | 82 | pub use hir_def::{ |
83 | builtin_type::BuiltinType, | 83 | builtin_type::BuiltinType, |
84 | nameres::{ | 84 | nameres::{per_ns::PerNs, raw::ImportId}, |
85 | per_ns::{Namespace, PerNs}, | ||
86 | raw::ImportId, | ||
87 | }, | ||
88 | path::{Path, PathKind}, | 85 | path::{Path, PathKind}, |
89 | type_ref::Mutability, | 86 | type_ref::Mutability, |
90 | }; | 87 | }; |
diff --git a/crates/ra_hir/src/mock.rs b/crates/ra_hir/src/mock.rs deleted file mode 100644 index ab97a09b9..000000000 --- a/crates/ra_hir/src/mock.rs +++ /dev/null | |||
@@ -1,262 +0,0 @@ | |||
1 | //! FIXME: write short doc here | ||
2 | |||
3 | use std::{panic, sync::Arc}; | ||
4 | |||
5 | use hir_expand::diagnostics::DiagnosticSink; | ||
6 | use parking_lot::Mutex; | ||
7 | use ra_cfg::CfgOptions; | ||
8 | use ra_db::{ | ||
9 | salsa, CrateGraph, CrateId, Edition, FileId, FileLoader, FileLoaderDelegate, FilePosition, | ||
10 | RelativePath, RelativePathBuf, SourceDatabase, SourceDatabaseExt, SourceRoot, SourceRootId, | ||
11 | }; | ||
12 | use rustc_hash::FxHashMap; | ||
13 | use test_utils::{extract_offset, parse_fixture, CURSOR_MARKER}; | ||
14 | |||
15 | use crate::{db, debug::HirDebugHelper}; | ||
16 | |||
17 | pub const WORKSPACE: SourceRootId = SourceRootId(0); | ||
18 | |||
19 | #[salsa::database( | ||
20 | ra_db::SourceDatabaseExtStorage, | ||
21 | ra_db::SourceDatabaseStorage, | ||
22 | db::InternDatabaseStorage, | ||
23 | db::AstDatabaseStorage, | ||
24 | db::DefDatabaseStorage, | ||
25 | db::DefDatabase2Storage, | ||
26 | db::HirDatabaseStorage | ||
27 | )] | ||
28 | #[derive(Debug)] | ||
29 | pub struct MockDatabase { | ||
30 | events: Mutex<Option<Vec<salsa::Event<MockDatabase>>>>, | ||
31 | runtime: salsa::Runtime<MockDatabase>, | ||
32 | files: FxHashMap<String, FileId>, | ||
33 | crate_names: Arc<FxHashMap<CrateId, String>>, | ||
34 | file_paths: Arc<FxHashMap<FileId, String>>, | ||
35 | } | ||
36 | |||
37 | impl panic::RefUnwindSafe for MockDatabase {} | ||
38 | |||
39 | impl FileLoader for MockDatabase { | ||
40 | fn file_text(&self, file_id: FileId) -> Arc<String> { | ||
41 | FileLoaderDelegate(self).file_text(file_id) | ||
42 | } | ||
43 | fn resolve_relative_path( | ||
44 | &self, | ||
45 | anchor: FileId, | ||
46 | relative_path: &RelativePath, | ||
47 | ) -> Option<FileId> { | ||
48 | FileLoaderDelegate(self).resolve_relative_path(anchor, relative_path) | ||
49 | } | ||
50 | fn relevant_crates(&self, file_id: FileId) -> Arc<Vec<CrateId>> { | ||
51 | FileLoaderDelegate(self).relevant_crates(file_id) | ||
52 | } | ||
53 | } | ||
54 | |||
55 | impl HirDebugHelper for MockDatabase { | ||
56 | fn crate_name(&self, krate: CrateId) -> Option<String> { | ||
57 | self.crate_names.get(&krate).cloned() | ||
58 | } | ||
59 | |||
60 | fn file_path(&self, file_id: FileId) -> Option<String> { | ||
61 | self.file_paths.get(&file_id).cloned() | ||
62 | } | ||
63 | } | ||
64 | |||
65 | impl MockDatabase { | ||
66 | pub fn with_files(fixture: &str) -> MockDatabase { | ||
67 | let (db, position) = MockDatabase::from_fixture(fixture); | ||
68 | assert!(position.is_none()); | ||
69 | db | ||
70 | } | ||
71 | |||
72 | pub fn with_single_file(text: &str) -> (MockDatabase, SourceRoot, FileId) { | ||
73 | let mut db = MockDatabase::default(); | ||
74 | let mut source_root = SourceRoot::default(); | ||
75 | let file_id = db.add_file(WORKSPACE, "/", &mut source_root, "/main.rs", text); | ||
76 | db.set_source_root(WORKSPACE, Arc::new(source_root.clone())); | ||
77 | (db, source_root, file_id) | ||
78 | } | ||
79 | |||
80 | pub fn file_id_of(&self, path: &str) -> FileId { | ||
81 | match self.files.get(path) { | ||
82 | Some(it) => *it, | ||
83 | None => panic!("unknown file: {:?}\nexisting files:\n{:#?}", path, self.files), | ||
84 | } | ||
85 | } | ||
86 | |||
87 | pub fn diagnostics(&self) -> String { | ||
88 | let mut buf = String::new(); | ||
89 | let mut files: Vec<FileId> = self.files.values().copied().collect(); | ||
90 | files.sort(); | ||
91 | for file in files { | ||
92 | let src = crate::Source { | ||
93 | file_id: file.into(), | ||
94 | ast: crate::ModuleSource::new(self, Some(file), None), | ||
95 | }; | ||
96 | let module = crate::Module::from_definition(self, src).unwrap(); | ||
97 | module.diagnostics( | ||
98 | self, | ||
99 | &mut DiagnosticSink::new(|d| { | ||
100 | buf += &format!("{:?}: {}\n", d.syntax_node(self).text(), d.message()); | ||
101 | }), | ||
102 | ) | ||
103 | } | ||
104 | buf | ||
105 | } | ||
106 | |||
107 | fn from_fixture(fixture: &str) -> (MockDatabase, Option<FilePosition>) { | ||
108 | let mut db = MockDatabase::default(); | ||
109 | |||
110 | let pos = db.add_fixture(fixture); | ||
111 | |||
112 | (db, pos) | ||
113 | } | ||
114 | |||
115 | fn add_fixture(&mut self, fixture: &str) -> Option<FilePosition> { | ||
116 | let mut position = None; | ||
117 | let mut source_root = SourceRoot::default(); | ||
118 | let mut source_root_id = WORKSPACE; | ||
119 | let mut source_root_prefix = "/".to_string(); | ||
120 | for entry in parse_fixture(fixture) { | ||
121 | if entry.meta.starts_with("root") { | ||
122 | self.set_source_root(source_root_id, Arc::new(source_root)); | ||
123 | source_root = SourceRoot::default(); | ||
124 | |||
125 | source_root_id = SourceRootId(source_root_id.0 + 1); | ||
126 | source_root_prefix = entry.meta["root".len()..].trim().to_string(); | ||
127 | continue; | ||
128 | } | ||
129 | if entry.text.contains(CURSOR_MARKER) { | ||
130 | assert!(position.is_none(), "only one marker (<|>) per fixture is allowed"); | ||
131 | position = Some(self.add_file_with_position( | ||
132 | source_root_id, | ||
133 | &source_root_prefix, | ||
134 | &mut source_root, | ||
135 | &entry.meta, | ||
136 | &entry.text, | ||
137 | )); | ||
138 | } else { | ||
139 | self.add_file( | ||
140 | source_root_id, | ||
141 | &source_root_prefix, | ||
142 | &mut source_root, | ||
143 | &entry.meta, | ||
144 | &entry.text, | ||
145 | ); | ||
146 | } | ||
147 | } | ||
148 | self.set_source_root(source_root_id, Arc::new(source_root)); | ||
149 | position | ||
150 | } | ||
151 | |||
152 | fn add_file( | ||
153 | &mut self, | ||
154 | source_root_id: SourceRootId, | ||
155 | source_root_prefix: &str, | ||
156 | source_root: &mut SourceRoot, | ||
157 | path: &str, | ||
158 | text: &str, | ||
159 | ) -> FileId { | ||
160 | assert!(source_root_prefix.starts_with('/')); | ||
161 | assert!(source_root_prefix.ends_with('/')); | ||
162 | assert!(path.starts_with(source_root_prefix)); | ||
163 | let rel_path = RelativePathBuf::from_path(&path[source_root_prefix.len()..]).unwrap(); | ||
164 | |||
165 | let is_crate_root = rel_path == "lib.rs" || rel_path == "/main.rs"; | ||
166 | |||
167 | let file_id = FileId(self.files.len() as u32); | ||
168 | |||
169 | let prev = self.files.insert(path.to_string(), file_id); | ||
170 | assert!(prev.is_none(), "duplicate files in the text fixture"); | ||
171 | Arc::make_mut(&mut self.file_paths).insert(file_id, path.to_string()); | ||
172 | |||
173 | let text = Arc::new(text.to_string()); | ||
174 | self.set_file_text(file_id, text); | ||
175 | self.set_file_relative_path(file_id, rel_path.clone()); | ||
176 | self.set_file_source_root(file_id, source_root_id); | ||
177 | source_root.insert_file(rel_path, file_id); | ||
178 | |||
179 | if is_crate_root { | ||
180 | let mut crate_graph = CrateGraph::default(); | ||
181 | crate_graph.add_crate_root(file_id, Edition::Edition2018, CfgOptions::default()); | ||
182 | self.set_crate_graph(Arc::new(crate_graph)); | ||
183 | } | ||
184 | file_id | ||
185 | } | ||
186 | |||
187 | fn add_file_with_position( | ||
188 | &mut self, | ||
189 | source_root_id: SourceRootId, | ||
190 | source_root_prefix: &str, | ||
191 | source_root: &mut SourceRoot, | ||
192 | path: &str, | ||
193 | text: &str, | ||
194 | ) -> FilePosition { | ||
195 | let (offset, text) = extract_offset(text); | ||
196 | let file_id = self.add_file(source_root_id, source_root_prefix, source_root, path, &text); | ||
197 | FilePosition { file_id, offset } | ||
198 | } | ||
199 | } | ||
200 | |||
201 | impl salsa::Database for MockDatabase { | ||
202 | fn salsa_runtime(&self) -> &salsa::Runtime<MockDatabase> { | ||
203 | &self.runtime | ||
204 | } | ||
205 | |||
206 | fn salsa_event(&self, event: impl Fn() -> salsa::Event<MockDatabase>) { | ||
207 | let mut events = self.events.lock(); | ||
208 | if let Some(events) = &mut *events { | ||
209 | events.push(event()); | ||
210 | } | ||
211 | } | ||
212 | } | ||
213 | |||
214 | impl Default for MockDatabase { | ||
215 | fn default() -> MockDatabase { | ||
216 | let mut db = MockDatabase { | ||
217 | events: Default::default(), | ||
218 | runtime: salsa::Runtime::default(), | ||
219 | files: FxHashMap::default(), | ||
220 | crate_names: Default::default(), | ||
221 | file_paths: Default::default(), | ||
222 | }; | ||
223 | db.set_crate_graph(Default::default()); | ||
224 | db | ||
225 | } | ||
226 | } | ||
227 | |||
228 | impl salsa::ParallelDatabase for MockDatabase { | ||
229 | fn snapshot(&self) -> salsa::Snapshot<MockDatabase> { | ||
230 | salsa::Snapshot::new(MockDatabase { | ||
231 | events: Default::default(), | ||
232 | runtime: self.runtime.snapshot(self), | ||
233 | // only the root database can be used to get file_id by path. | ||
234 | files: FxHashMap::default(), | ||
235 | file_paths: Arc::clone(&self.file_paths), | ||
236 | crate_names: Arc::clone(&self.crate_names), | ||
237 | }) | ||
238 | } | ||
239 | } | ||
240 | |||
241 | impl MockDatabase { | ||
242 | pub fn log(&self, f: impl FnOnce()) -> Vec<salsa::Event<MockDatabase>> { | ||
243 | *self.events.lock() = Some(Vec::new()); | ||
244 | f(); | ||
245 | self.events.lock().take().unwrap() | ||
246 | } | ||
247 | |||
248 | pub fn log_executed(&self, f: impl FnOnce()) -> Vec<String> { | ||
249 | let events = self.log(f); | ||
250 | events | ||
251 | .into_iter() | ||
252 | .filter_map(|e| match e.kind { | ||
253 | // This pretty horrible, but `Debug` is the only way to inspect | ||
254 | // QueryDescriptor at the moment. | ||
255 | salsa::EventKind::WillExecute { database_key } => { | ||
256 | Some(format!("{:?}", database_key)) | ||
257 | } | ||
258 | _ => None, | ||
259 | }) | ||
260 | .collect() | ||
261 | } | ||
262 | } | ||
diff --git a/crates/ra_hir/src/test_db.rs b/crates/ra_hir/src/test_db.rs new file mode 100644 index 000000000..5237b303a --- /dev/null +++ b/crates/ra_hir/src/test_db.rs | |||
@@ -0,0 +1,120 @@ | |||
1 | //! Database used for testing `hir`. | ||
2 | |||
3 | use std::{panic, sync::Arc}; | ||
4 | |||
5 | use hir_def::{db::DefDatabase2, ModuleId}; | ||
6 | use hir_expand::diagnostics::DiagnosticSink; | ||
7 | use parking_lot::Mutex; | ||
8 | use ra_db::{salsa, CrateId, FileId, FileLoader, FileLoaderDelegate, RelativePath, SourceDatabase}; | ||
9 | |||
10 | use crate::{db, debug::HirDebugHelper}; | ||
11 | |||
12 | #[salsa::database( | ||
13 | ra_db::SourceDatabaseExtStorage, | ||
14 | ra_db::SourceDatabaseStorage, | ||
15 | db::InternDatabaseStorage, | ||
16 | db::AstDatabaseStorage, | ||
17 | db::DefDatabaseStorage, | ||
18 | db::DefDatabase2Storage, | ||
19 | db::HirDatabaseStorage | ||
20 | )] | ||
21 | #[derive(Debug, Default)] | ||
22 | pub struct TestDB { | ||
23 | events: Mutex<Option<Vec<salsa::Event<TestDB>>>>, | ||
24 | runtime: salsa::Runtime<TestDB>, | ||
25 | } | ||
26 | |||
27 | impl salsa::Database for TestDB { | ||
28 | fn salsa_runtime(&self) -> &salsa::Runtime<TestDB> { | ||
29 | &self.runtime | ||
30 | } | ||
31 | |||
32 | fn salsa_event(&self, event: impl Fn() -> salsa::Event<TestDB>) { | ||
33 | let mut events = self.events.lock(); | ||
34 | if let Some(events) = &mut *events { | ||
35 | events.push(event()); | ||
36 | } | ||
37 | } | ||
38 | } | ||
39 | |||
40 | impl salsa::ParallelDatabase for TestDB { | ||
41 | fn snapshot(&self) -> salsa::Snapshot<TestDB> { | ||
42 | salsa::Snapshot::new(TestDB { | ||
43 | events: Default::default(), | ||
44 | runtime: self.runtime.snapshot(self), | ||
45 | }) | ||
46 | } | ||
47 | } | ||
48 | |||
49 | impl panic::RefUnwindSafe for TestDB {} | ||
50 | |||
51 | impl FileLoader for TestDB { | ||
52 | fn file_text(&self, file_id: FileId) -> Arc<String> { | ||
53 | FileLoaderDelegate(self).file_text(file_id) | ||
54 | } | ||
55 | fn resolve_relative_path( | ||
56 | &self, | ||
57 | anchor: FileId, | ||
58 | relative_path: &RelativePath, | ||
59 | ) -> Option<FileId> { | ||
60 | FileLoaderDelegate(self).resolve_relative_path(anchor, relative_path) | ||
61 | } | ||
62 | fn relevant_crates(&self, file_id: FileId) -> Arc<Vec<CrateId>> { | ||
63 | FileLoaderDelegate(self).relevant_crates(file_id) | ||
64 | } | ||
65 | } | ||
66 | |||
67 | // FIXME: improve `WithFixture` to bring useful hir debugging back | ||
68 | impl HirDebugHelper for TestDB { | ||
69 | fn crate_name(&self, _krate: CrateId) -> Option<String> { | ||
70 | None | ||
71 | } | ||
72 | |||
73 | fn file_path(&self, _file_id: FileId) -> Option<String> { | ||
74 | None | ||
75 | } | ||
76 | } | ||
77 | |||
78 | impl TestDB { | ||
79 | pub fn diagnostics(&self) -> String { | ||
80 | let mut buf = String::new(); | ||
81 | let crate_graph = self.crate_graph(); | ||
82 | for krate in crate_graph.iter().next() { | ||
83 | let crate_def_map = self.crate_def_map(krate); | ||
84 | for (module_id, _) in crate_def_map.modules.iter() { | ||
85 | let module_id = ModuleId { krate, module_id }; | ||
86 | let module = crate::Module::from(module_id); | ||
87 | module.diagnostics( | ||
88 | self, | ||
89 | &mut DiagnosticSink::new(|d| { | ||
90 | buf += &format!("{:?}: {}\n", d.syntax_node(self).text(), d.message()); | ||
91 | }), | ||
92 | ) | ||
93 | } | ||
94 | } | ||
95 | buf | ||
96 | } | ||
97 | } | ||
98 | |||
99 | impl TestDB { | ||
100 | pub fn log(&self, f: impl FnOnce()) -> Vec<salsa::Event<TestDB>> { | ||
101 | *self.events.lock() = Some(Vec::new()); | ||
102 | f(); | ||
103 | self.events.lock().take().unwrap() | ||
104 | } | ||
105 | |||
106 | pub fn log_executed(&self, f: impl FnOnce()) -> Vec<String> { | ||
107 | let events = self.log(f); | ||
108 | events | ||
109 | .into_iter() | ||
110 | .filter_map(|e| match e.kind { | ||
111 | // This pretty horrible, but `Debug` is the only way to inspect | ||
112 | // QueryDescriptor at the moment. | ||
113 | salsa::EventKind::WillExecute { database_key } => { | ||
114 | Some(format!("{:?}", database_key)) | ||
115 | } | ||
116 | _ => None, | ||
117 | }) | ||
118 | .collect() | ||
119 | } | ||
120 | } | ||
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index d1a9d7411..cd2ac0e8b 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -27,7 +27,7 @@ pub(crate) use infer::{infer_query, InferTy, InferenceResult}; | |||
27 | pub use lower::CallableDef; | 27 | pub use lower::CallableDef; |
28 | pub(crate) use lower::{ | 28 | pub(crate) use lower::{ |
29 | callable_item_sig, generic_defaults_query, generic_predicates_for_param_query, | 29 | callable_item_sig, generic_defaults_query, generic_predicates_for_param_query, |
30 | generic_predicates_query, type_for_def, type_for_field, TypableDef, | 30 | generic_predicates_query, type_for_def, type_for_field, Namespace, TypableDef, |
31 | }; | 31 | }; |
32 | pub(crate) use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment}; | 32 | pub(crate) use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment}; |
33 | 33 | ||
diff --git a/crates/ra_hir/src/ty/infer/expr.rs b/crates/ra_hir/src/ty/infer/expr.rs index a09ef5c5d..4af1d65ee 100644 --- a/crates/ra_hir/src/ty/infer/expr.rs +++ b/crates/ra_hir/src/ty/infer/expr.rs | |||
@@ -12,10 +12,10 @@ use crate::{ | |||
12 | expr::{self, Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp}, | 12 | expr::{self, Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp}, |
13 | generics::{GenericParams, HasGenericParams}, | 13 | generics::{GenericParams, HasGenericParams}, |
14 | ty::{ | 14 | ty::{ |
15 | autoderef, method_resolution, op, primitive, CallableDef, InferTy, Mutability, Obligation, | 15 | autoderef, method_resolution, op, primitive, CallableDef, InferTy, Mutability, Namespace, |
16 | ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk, | 16 | Obligation, ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk, |
17 | }, | 17 | }, |
18 | Adt, Name, Namespace, | 18 | Adt, Name, |
19 | }; | 19 | }; |
20 | 20 | ||
21 | impl<'a, D: HirDatabase> InferenceContext<'a, D> { | 21 | impl<'a, D: HirDatabase> InferenceContext<'a, D> { |
diff --git a/crates/ra_hir/src/ty/infer/path.rs b/crates/ra_hir/src/ty/infer/path.rs index 59b7f7eb6..865ced5a1 100644 --- a/crates/ra_hir/src/ty/infer/path.rs +++ b/crates/ra_hir/src/ty/infer/path.rs | |||
@@ -6,8 +6,8 @@ use super::{ExprOrPatId, InferenceContext, TraitRef}; | |||
6 | use crate::{ | 6 | use crate::{ |
7 | db::HirDatabase, | 7 | db::HirDatabase, |
8 | resolve::{ResolveValueResult, Resolver, TypeNs, ValueNs}, | 8 | resolve::{ResolveValueResult, Resolver, TypeNs, ValueNs}, |
9 | ty::{method_resolution, Substs, Ty, TypableDef, TypeWalk}, | 9 | ty::{method_resolution, Namespace, Substs, Ty, TypableDef, TypeWalk}, |
10 | AssocItem, Container, HasGenericParams, Name, Namespace, Path, | 10 | AssocItem, Container, HasGenericParams, Name, Path, |
11 | }; | 11 | }; |
12 | 12 | ||
13 | impl<'a, D: HirDatabase> InferenceContext<'a, D> { | 13 | impl<'a, D: HirDatabase> InferenceContext<'a, D> { |
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs index e29ab8492..d26b16cb2 100644 --- a/crates/ra_hir/src/ty/lower.rs +++ b/crates/ra_hir/src/ty/lower.rs | |||
@@ -29,10 +29,21 @@ use crate::{ | |||
29 | Adt, | 29 | Adt, |
30 | }, | 30 | }, |
31 | util::make_mut_slice, | 31 | util::make_mut_slice, |
32 | Const, Enum, EnumVariant, Function, ModuleDef, Namespace, Path, Static, Struct, StructField, | 32 | Const, Enum, EnumVariant, Function, ModuleDef, Path, Static, Struct, StructField, Trait, |
33 | Trait, TypeAlias, Union, | 33 | TypeAlias, Union, |
34 | }; | 34 | }; |
35 | 35 | ||
36 | // FIXME: this is only really used in `type_for_def`, which contains a bunch of | ||
37 | // impossible cases. Perhaps we should recombine `TypeableDef` and `Namespace` | ||
38 | // into a `AsTypeDef`, `AsValueDef` enums? | ||
39 | #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] | ||
40 | pub enum Namespace { | ||
41 | Types, | ||
42 | Values, | ||
43 | // Note that only type inference uses this enum, and it doesn't care about macros. | ||
44 | // Macro, | ||
45 | } | ||
46 | |||
36 | impl Ty { | 47 | impl Ty { |
37 | pub(crate) fn from_hir(db: &impl HirDatabase, resolver: &Resolver, type_ref: &TypeRef) -> Self { | 48 | pub(crate) fn from_hir(db: &impl HirDatabase, resolver: &Resolver, type_ref: &TypeRef) -> Self { |
38 | match type_ref { | 49 | match type_ref { |
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index 4b7e34878..e56b9356e 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs | |||
@@ -11,7 +11,7 @@ use ra_syntax::{ | |||
11 | use test_utils::covers; | 11 | use test_utils::covers; |
12 | 12 | ||
13 | use crate::{ | 13 | use crate::{ |
14 | expr::BodySourceMap, mock::MockDatabase, ty::display::HirDisplay, ty::InferenceResult, | 14 | expr::BodySourceMap, test_db::TestDB, ty::display::HirDisplay, ty::InferenceResult, |
15 | SourceAnalyzer, | 15 | SourceAnalyzer, |
16 | }; | 16 | }; |
17 | 17 | ||
@@ -24,7 +24,7 @@ mod coercion; | |||
24 | 24 | ||
25 | #[test] | 25 | #[test] |
26 | fn cfg_impl_block() { | 26 | fn cfg_impl_block() { |
27 | let (db, pos) = MockDatabase::with_position( | 27 | let (db, pos) = TestDB::with_position( |
28 | r#" | 28 | r#" |
29 | //- /main.rs crate:main deps:foo cfg:test | 29 | //- /main.rs crate:main deps:foo cfg:test |
30 | use foo::S as T; | 30 | use foo::S as T; |
@@ -64,7 +64,7 @@ impl S { | |||
64 | 64 | ||
65 | #[test] | 65 | #[test] |
66 | fn infer_await() { | 66 | fn infer_await() { |
67 | let (db, pos) = MockDatabase::with_position( | 67 | let (db, pos) = TestDB::with_position( |
68 | r#" | 68 | r#" |
69 | //- /main.rs crate:main deps:std | 69 | //- /main.rs crate:main deps:std |
70 | 70 | ||
@@ -95,7 +95,7 @@ mod future { | |||
95 | 95 | ||
96 | #[test] | 96 | #[test] |
97 | fn infer_box() { | 97 | fn infer_box() { |
98 | let (db, pos) = MockDatabase::with_position( | 98 | let (db, pos) = TestDB::with_position( |
99 | r#" | 99 | r#" |
100 | //- /main.rs crate:main deps:std | 100 | //- /main.rs crate:main deps:std |
101 | 101 | ||
@@ -122,7 +122,7 @@ mod boxed { | |||
122 | 122 | ||
123 | #[test] | 123 | #[test] |
124 | fn infer_adt_self() { | 124 | fn infer_adt_self() { |
125 | let (db, pos) = MockDatabase::with_position( | 125 | let (db, pos) = TestDB::with_position( |
126 | r#" | 126 | r#" |
127 | //- /main.rs | 127 | //- /main.rs |
128 | enum Nat { Succ(Self), Demo(Nat), Zero } | 128 | enum Nat { Succ(Self), Demo(Nat), Zero } |
@@ -141,7 +141,7 @@ fn test() { | |||
141 | 141 | ||
142 | #[test] | 142 | #[test] |
143 | fn infer_try() { | 143 | fn infer_try() { |
144 | let (db, pos) = MockDatabase::with_position( | 144 | let (db, pos) = TestDB::with_position( |
145 | r#" | 145 | r#" |
146 | //- /main.rs crate:main deps:std | 146 | //- /main.rs crate:main deps:std |
147 | 147 | ||
@@ -181,7 +181,7 @@ mod result { | |||
181 | 181 | ||
182 | #[test] | 182 | #[test] |
183 | fn infer_for_loop() { | 183 | fn infer_for_loop() { |
184 | let (db, pos) = MockDatabase::with_position( | 184 | let (db, pos) = TestDB::with_position( |
185 | r#" | 185 | r#" |
186 | //- /main.rs crate:main deps:std | 186 | //- /main.rs crate:main deps:std |
187 | 187 | ||
@@ -223,7 +223,7 @@ mod collections { | |||
223 | #[test] | 223 | #[test] |
224 | fn infer_while_let() { | 224 | fn infer_while_let() { |
225 | covers!(infer_while_let); | 225 | covers!(infer_while_let); |
226 | let (db, pos) = MockDatabase::with_position( | 226 | let (db, pos) = TestDB::with_position( |
227 | r#" | 227 | r#" |
228 | //- /main.rs | 228 | //- /main.rs |
229 | enum Option<T> { Some(T), None } | 229 | enum Option<T> { Some(T), None } |
@@ -2484,7 +2484,7 @@ pub fn main_loop() { | |||
2484 | 2484 | ||
2485 | #[test] | 2485 | #[test] |
2486 | fn cross_crate_associated_method_call() { | 2486 | fn cross_crate_associated_method_call() { |
2487 | let (db, pos) = MockDatabase::with_position( | 2487 | let (db, pos) = TestDB::with_position( |
2488 | r#" | 2488 | r#" |
2489 | //- /main.rs crate:main deps:other_crate | 2489 | //- /main.rs crate:main deps:other_crate |
2490 | fn test() { | 2490 | fn test() { |
@@ -3378,7 +3378,7 @@ fn test() { S.foo()<|>; } | |||
3378 | 3378 | ||
3379 | #[test] | 3379 | #[test] |
3380 | fn infer_macro_with_dollar_crate_is_correct_in_expr() { | 3380 | fn infer_macro_with_dollar_crate_is_correct_in_expr() { |
3381 | let (db, pos) = MockDatabase::with_position( | 3381 | let (db, pos) = TestDB::with_position( |
3382 | r#" | 3382 | r#" |
3383 | //- /main.rs crate:main deps:foo | 3383 | //- /main.rs crate:main deps:foo |
3384 | fn test() { | 3384 | fn test() { |
@@ -3482,7 +3482,7 @@ fn test() { (&S).foo()<|>; } | |||
3482 | 3482 | ||
3483 | #[test] | 3483 | #[test] |
3484 | fn method_resolution_trait_from_prelude() { | 3484 | fn method_resolution_trait_from_prelude() { |
3485 | let (db, pos) = MockDatabase::with_position( | 3485 | let (db, pos) = TestDB::with_position( |
3486 | r#" | 3486 | r#" |
3487 | //- /main.rs crate:main deps:other_crate | 3487 | //- /main.rs crate:main deps:other_crate |
3488 | struct S; | 3488 | struct S; |
@@ -4651,7 +4651,7 @@ fn test<T, U>() where T: Trait<U::Item>, U: Trait<T::Item> { | |||
4651 | assert_eq!(t, "{unknown}"); | 4651 | assert_eq!(t, "{unknown}"); |
4652 | } | 4652 | } |
4653 | 4653 | ||
4654 | fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String { | 4654 | fn type_at_pos(db: &TestDB, pos: FilePosition) -> String { |
4655 | let file = db.parse(pos.file_id).ok().unwrap(); | 4655 | let file = db.parse(pos.file_id).ok().unwrap(); |
4656 | let expr = algo::find_node_at_offset::<ast::Expr>(file.syntax(), pos.offset).unwrap(); | 4656 | let expr = algo::find_node_at_offset::<ast::Expr>(file.syntax(), pos.offset).unwrap(); |
4657 | let analyzer = SourceAnalyzer::new(db, pos.file_id, expr.syntax(), Some(pos.offset)); | 4657 | let analyzer = SourceAnalyzer::new(db, pos.file_id, expr.syntax(), Some(pos.offset)); |
@@ -4660,12 +4660,12 @@ fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String { | |||
4660 | } | 4660 | } |
4661 | 4661 | ||
4662 | fn type_at(content: &str) -> String { | 4662 | fn type_at(content: &str) -> String { |
4663 | let (db, file_pos) = MockDatabase::with_position(content); | 4663 | let (db, file_pos) = TestDB::with_position(content); |
4664 | type_at_pos(&db, file_pos) | 4664 | type_at_pos(&db, file_pos) |
4665 | } | 4665 | } |
4666 | 4666 | ||
4667 | fn infer(content: &str) -> String { | 4667 | fn infer(content: &str) -> String { |
4668 | let (db, _, file_id) = MockDatabase::with_single_file(content); | 4668 | let (db, file_id) = TestDB::with_single_file(content); |
4669 | let source_file = db.parse(file_id).ok().unwrap(); | 4669 | let source_file = db.parse(file_id).ok().unwrap(); |
4670 | 4670 | ||
4671 | let mut acc = String::new(); | 4671 | let mut acc = String::new(); |
@@ -4748,7 +4748,7 @@ fn ellipsize(mut text: String, max_len: usize) -> String { | |||
4748 | 4748 | ||
4749 | #[test] | 4749 | #[test] |
4750 | fn typing_whitespace_inside_a_function_should_not_invalidate_types() { | 4750 | fn typing_whitespace_inside_a_function_should_not_invalidate_types() { |
4751 | let (mut db, pos) = MockDatabase::with_position( | 4751 | let (mut db, pos) = TestDB::with_position( |
4752 | " | 4752 | " |
4753 | //- /lib.rs | 4753 | //- /lib.rs |
4754 | fn foo() -> i32 { | 4754 | fn foo() -> i32 { |
@@ -4788,7 +4788,7 @@ fn typing_whitespace_inside_a_function_should_not_invalidate_types() { | |||
4788 | 4788 | ||
4789 | #[test] | 4789 | #[test] |
4790 | fn no_such_field_diagnostics() { | 4790 | fn no_such_field_diagnostics() { |
4791 | let diagnostics = MockDatabase::with_files( | 4791 | let diagnostics = TestDB::with_files( |
4792 | r" | 4792 | r" |
4793 | //- /lib.rs | 4793 | //- /lib.rs |
4794 | struct S { foo: i32, bar: () } | 4794 | struct S { foo: i32, bar: () } |
diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs index 39ef92182..c694952f3 100644 --- a/crates/ra_hir/src/ty/traits/chalk.rs +++ b/crates/ra_hir/src/ty/traits/chalk.rs | |||
@@ -18,7 +18,10 @@ use crate::{ | |||
18 | db::HirDatabase, | 18 | db::HirDatabase, |
19 | generics::GenericDef, | 19 | generics::GenericDef, |
20 | ty::display::HirDisplay, | 20 | ty::display::HirDisplay, |
21 | ty::{ApplicationTy, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk}, | 21 | ty::{ |
22 | ApplicationTy, GenericPredicate, Namespace, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, | ||
23 | TypeWalk, | ||
24 | }, | ||
22 | AssocItem, Crate, HasGenericParams, ImplBlock, Trait, TypeAlias, | 25 | AssocItem, Crate, HasGenericParams, ImplBlock, Trait, TypeAlias, |
23 | }; | 26 | }; |
24 | 27 | ||
@@ -652,7 +655,7 @@ fn impl_block_datum( | |||
652 | }) | 655 | }) |
653 | .filter_map(|t| { | 656 | .filter_map(|t| { |
654 | let assoc_ty = trait_.associated_type_by_name(db, &t.name(db))?; | 657 | let assoc_ty = trait_.associated_type_by_name(db, &t.name(db))?; |
655 | let ty = db.type_for_def(t.into(), crate::Namespace::Types).subst(&bound_vars); | 658 | let ty = db.type_for_def(t.into(), Namespace::Types).subst(&bound_vars); |
656 | Some(chalk_rust_ir::AssociatedTyValue { | 659 | Some(chalk_rust_ir::AssociatedTyValue { |
657 | impl_id, | 660 | impl_id, |
658 | associated_ty_id: assoc_ty.to_chalk(db), | 661 | associated_ty_id: assoc_ty.to_chalk(db), |