diff options
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r-- | crates/ra_hir/src/db.rs | 3 | ||||
-rw-r--r-- | crates/ra_hir/src/debug.rs | 83 | ||||
-rw-r--r-- | crates/ra_hir/src/lib.rs | 1 | ||||
-rw-r--r-- | crates/ra_hir/src/mock.rs | 25 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 12 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/traits/chalk.rs | 12 |
6 files changed, 117 insertions, 19 deletions
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index 7b7974f5b..f7f124904 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs | |||
@@ -5,6 +5,7 @@ use ra_syntax::{ast, Parse, SmolStr, SyntaxNode}; | |||
5 | 5 | ||
6 | use crate::{ | 6 | use crate::{ |
7 | adt::{EnumData, StructData}, | 7 | adt::{EnumData, StructData}, |
8 | debug::HirDebugDatabase, | ||
8 | generics::{GenericDef, GenericParams}, | 9 | generics::{GenericDef, GenericParams}, |
9 | ids, | 10 | ids, |
10 | impl_block::{ImplBlock, ImplSourceMap, ModuleImplBlocks}, | 11 | impl_block::{ImplBlock, ImplSourceMap, ModuleImplBlocks}, |
@@ -83,7 +84,7 @@ pub trait AstDatabase: InternDatabase { | |||
83 | // This database uses `AstDatabase` internally, | 84 | // This database uses `AstDatabase` internally, |
84 | #[salsa::query_group(DefDatabaseStorage)] | 85 | #[salsa::query_group(DefDatabaseStorage)] |
85 | #[salsa::requires(AstDatabase)] | 86 | #[salsa::requires(AstDatabase)] |
86 | pub trait DefDatabase: InternDatabase { | 87 | pub trait DefDatabase: InternDatabase + HirDebugDatabase { |
87 | #[salsa::invoke(crate::adt::StructData::struct_data_query)] | 88 | #[salsa::invoke(crate::adt::StructData::struct_data_query)] |
88 | fn struct_data(&self, s: Struct) -> Arc<StructData>; | 89 | fn struct_data(&self, s: Struct) -> Arc<StructData>; |
89 | 90 | ||
diff --git a/crates/ra_hir/src/debug.rs b/crates/ra_hir/src/debug.rs new file mode 100644 index 000000000..87f3180c3 --- /dev/null +++ b/crates/ra_hir/src/debug.rs | |||
@@ -0,0 +1,83 @@ | |||
1 | //! printf debugging infrastructure for rust-analyzer. | ||
2 | //! | ||
3 | //! When you print a hir type, like a module, using `eprintln!("{:?}", module)`, | ||
4 | //! you usually get back a numeric ID, which doesn't tell you much: | ||
5 | //! `Module(92)`. | ||
6 | //! | ||
7 | //! This module adds convenience `debug` methods to various types, which resolve | ||
8 | //! the id to a human-readable location info: | ||
9 | //! | ||
10 | //! ```not_rust | ||
11 | //! eprintln!("{:?}", module.debug(db)); | ||
12 | //! => | ||
13 | //! Module { name: collections, path: "liballoc/collections/mod.rs" } | ||
14 | //! ``` | ||
15 | //! | ||
16 | //! Note that to get this info, we might need to execute queries! So | ||
17 | //! | ||
18 | //! * don't use the `debug` methods for logging | ||
19 | //! * when debugging, be aware that interference is possible. | ||
20 | |||
21 | use std::fmt; | ||
22 | |||
23 | use ra_db::{CrateId, FileId}; | ||
24 | |||
25 | use crate::{db::HirDatabase, Crate, Module, Name}; | ||
26 | |||
27 | impl Crate { | ||
28 | pub fn debug(self, db: &impl HirDebugDatabase) -> impl fmt::Debug + '_ { | ||
29 | debug_fn(move |fmt| db.debug_crate(self, fmt)) | ||
30 | } | ||
31 | } | ||
32 | |||
33 | impl Module { | ||
34 | pub fn debug(self, db: &impl HirDebugDatabase) -> impl fmt::Debug + '_ { | ||
35 | debug_fn(move |fmt| db.debug_module(self, fmt)) | ||
36 | } | ||
37 | } | ||
38 | |||
39 | pub trait HirDebugHelper: HirDatabase { | ||
40 | fn crate_name(&self, _krate: CrateId) -> Option<String> { | ||
41 | None | ||
42 | } | ||
43 | fn file_path(&self, _file_id: FileId) -> Option<String> { | ||
44 | None | ||
45 | } | ||
46 | } | ||
47 | |||
48 | pub trait HirDebugDatabase { | ||
49 | fn debug_crate(&self, krate: Crate, fmt: &mut fmt::Formatter<'_>) -> fmt::Result; | ||
50 | fn debug_module(&self, module: Module, fmt: &mut fmt::Formatter<'_>) -> fmt::Result; | ||
51 | } | ||
52 | |||
53 | impl<DB: HirDebugHelper> HirDebugDatabase for DB { | ||
54 | fn debug_crate(&self, krate: Crate, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
55 | let mut builder = fmt.debug_tuple("Crate"); | ||
56 | match self.crate_name(krate.crate_id) { | ||
57 | Some(name) => builder.field(&name), | ||
58 | None => builder.field(&krate.crate_id), | ||
59 | } | ||
60 | .finish() | ||
61 | } | ||
62 | |||
63 | fn debug_module(&self, module: Module, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
64 | let file_id = module.definition_source(self).file_id.original_file(self); | ||
65 | let path = self.file_path(file_id); | ||
66 | fmt.debug_struct("Module") | ||
67 | .field("name", &module.name(self).unwrap_or_else(Name::missing)) | ||
68 | .field("path", &path.unwrap_or_else(|| "N/A".to_string())) | ||
69 | .finish() | ||
70 | } | ||
71 | } | ||
72 | |||
73 | fn debug_fn(f: impl Fn(&mut fmt::Formatter<'_>) -> fmt::Result) -> impl fmt::Debug { | ||
74 | struct DebugFn<F>(F); | ||
75 | |||
76 | impl<F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result> fmt::Debug for DebugFn<F> { | ||
77 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
78 | (&self.0)(fmt) | ||
79 | } | ||
80 | } | ||
81 | |||
82 | DebugFn(f) | ||
83 | } | ||
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 7c2a68992..24ee84f86 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs | |||
@@ -20,6 +20,7 @@ macro_rules! impl_froms { | |||
20 | } | 20 | } |
21 | 21 | ||
22 | mod either; | 22 | mod either; |
23 | pub mod debug; | ||
23 | 24 | ||
24 | pub mod db; | 25 | pub mod db; |
25 | #[macro_use] | 26 | #[macro_use] |
diff --git a/crates/ra_hir/src/mock.rs b/crates/ra_hir/src/mock.rs index 972f0ece5..8dcea5071 100644 --- a/crates/ra_hir/src/mock.rs +++ b/crates/ra_hir/src/mock.rs | |||
@@ -2,13 +2,14 @@ use std::{panic, sync::Arc}; | |||
2 | 2 | ||
3 | use parking_lot::Mutex; | 3 | use parking_lot::Mutex; |
4 | use ra_db::{ | 4 | use ra_db::{ |
5 | salsa, CrateGraph, Edition, FileId, FilePosition, SourceDatabase, SourceRoot, SourceRootId, | 5 | salsa, CrateGraph, CrateId, Edition, FileId, FilePosition, SourceDatabase, SourceRoot, |
6 | SourceRootId, | ||
6 | }; | 7 | }; |
7 | use relative_path::RelativePathBuf; | 8 | use relative_path::RelativePathBuf; |
8 | use rustc_hash::FxHashMap; | 9 | use rustc_hash::FxHashMap; |
9 | use test_utils::{extract_offset, parse_fixture, CURSOR_MARKER}; | 10 | use test_utils::{extract_offset, parse_fixture, CURSOR_MARKER}; |
10 | 11 | ||
11 | use crate::{db, diagnostics::DiagnosticSink}; | 12 | use crate::{db, debug::HirDebugHelper, diagnostics::DiagnosticSink}; |
12 | 13 | ||
13 | pub const WORKSPACE: SourceRootId = SourceRootId(0); | 14 | pub const WORKSPACE: SourceRootId = SourceRootId(0); |
14 | 15 | ||
@@ -24,10 +25,22 @@ pub struct MockDatabase { | |||
24 | events: Mutex<Option<Vec<salsa::Event<MockDatabase>>>>, | 25 | events: Mutex<Option<Vec<salsa::Event<MockDatabase>>>>, |
25 | runtime: salsa::Runtime<MockDatabase>, | 26 | runtime: salsa::Runtime<MockDatabase>, |
26 | files: FxHashMap<String, FileId>, | 27 | files: FxHashMap<String, FileId>, |
28 | crate_names: Arc<FxHashMap<CrateId, String>>, | ||
29 | file_paths: Arc<FxHashMap<FileId, String>>, | ||
27 | } | 30 | } |
28 | 31 | ||
29 | impl panic::RefUnwindSafe for MockDatabase {} | 32 | impl panic::RefUnwindSafe for MockDatabase {} |
30 | 33 | ||
34 | impl HirDebugHelper for MockDatabase { | ||
35 | fn crate_name(&self, krate: CrateId) -> Option<String> { | ||
36 | self.crate_names.get(&krate).cloned() | ||
37 | } | ||
38 | |||
39 | fn file_path(&self, file_id: FileId) -> Option<String> { | ||
40 | self.file_paths.get(&file_id).cloned() | ||
41 | } | ||
42 | } | ||
43 | |||
31 | impl MockDatabase { | 44 | impl MockDatabase { |
32 | pub fn with_files(fixture: &str) -> MockDatabase { | 45 | pub fn with_files(fixture: &str) -> MockDatabase { |
33 | let (db, position) = MockDatabase::from_fixture(fixture); | 46 | let (db, position) = MockDatabase::from_fixture(fixture); |
@@ -62,6 +75,7 @@ impl MockDatabase { | |||
62 | for (crate_name, (crate_root, edition, _)) in graph.0.iter() { | 75 | for (crate_name, (crate_root, edition, _)) in graph.0.iter() { |
63 | let crate_root = self.file_id_of(&crate_root); | 76 | let crate_root = self.file_id_of(&crate_root); |
64 | let crate_id = crate_graph.add_crate_root(crate_root, *edition); | 77 | let crate_id = crate_graph.add_crate_root(crate_root, *edition); |
78 | Arc::make_mut(&mut self.crate_names).insert(crate_id, crate_name.clone()); | ||
65 | ids.insert(crate_name, crate_id); | 79 | ids.insert(crate_name, crate_id); |
66 | } | 80 | } |
67 | for (crate_name, (_, _, deps)) in graph.0.iter() { | 81 | for (crate_name, (_, _, deps)) in graph.0.iter() { |
@@ -151,8 +165,11 @@ impl MockDatabase { | |||
151 | let is_crate_root = rel_path == "lib.rs" || rel_path == "/main.rs"; | 165 | let is_crate_root = rel_path == "lib.rs" || rel_path == "/main.rs"; |
152 | 166 | ||
153 | let file_id = FileId(self.files.len() as u32); | 167 | let file_id = FileId(self.files.len() as u32); |
168 | |||
154 | let prev = self.files.insert(path.to_string(), file_id); | 169 | let prev = self.files.insert(path.to_string(), file_id); |
155 | assert!(prev.is_none(), "duplicate files in the text fixture"); | 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 | |||
156 | let text = Arc::new(text.to_string()); | 173 | let text = Arc::new(text.to_string()); |
157 | self.set_file_text(file_id, text); | 174 | self.set_file_text(file_id, text); |
158 | self.set_file_relative_path(file_id, rel_path.clone()); | 175 | self.set_file_relative_path(file_id, rel_path.clone()); |
@@ -200,6 +217,8 @@ impl Default for MockDatabase { | |||
200 | events: Default::default(), | 217 | events: Default::default(), |
201 | runtime: salsa::Runtime::default(), | 218 | runtime: salsa::Runtime::default(), |
202 | files: FxHashMap::default(), | 219 | files: FxHashMap::default(), |
220 | crate_names: Default::default(), | ||
221 | file_paths: Default::default(), | ||
203 | }; | 222 | }; |
204 | db.set_crate_graph(Default::default()); | 223 | db.set_crate_graph(Default::default()); |
205 | db | 224 | db |
@@ -213,6 +232,8 @@ impl salsa::ParallelDatabase for MockDatabase { | |||
213 | runtime: self.runtime.snapshot(self), | 232 | runtime: self.runtime.snapshot(self), |
214 | // only the root database can be used to get file_id by path. | 233 | // only the root database can be used to get file_id by path. |
215 | files: FxHashMap::default(), | 234 | files: FxHashMap::default(), |
235 | file_paths: Arc::clone(&self.file_paths), | ||
236 | crate_names: Arc::clone(&self.crate_names), | ||
216 | }) | 237 | }) |
217 | } | 238 | } |
218 | } | 239 | } |
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index 38fe62279..c60e72abf 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs | |||
@@ -3065,7 +3065,7 @@ impl<T, U> Into<U> for T where U: From<T> {} | |||
3065 | fn test() { S2.into()<|>; } | 3065 | fn test() { S2.into()<|>; } |
3066 | "#, | 3066 | "#, |
3067 | ); | 3067 | ); |
3068 | assert_eq!(t, "S1"); | 3068 | assert_eq!(t, "{unknown}"); |
3069 | } | 3069 | } |
3070 | 3070 | ||
3071 | #[test] | 3071 | #[test] |
@@ -3082,7 +3082,7 @@ impl<T, U: From<T>> Into<U> for T {} | |||
3082 | fn test() { S2.into()<|>; } | 3082 | fn test() { S2.into()<|>; } |
3083 | "#, | 3083 | "#, |
3084 | ); | 3084 | ); |
3085 | assert_eq!(t, "S1"); | 3085 | assert_eq!(t, "{unknown}"); |
3086 | } | 3086 | } |
3087 | 3087 | ||
3088 | #[test] | 3088 | #[test] |
@@ -3124,7 +3124,7 @@ impl<B, C> Trait for S<B, C> where C: FnX, B: SendX {} | |||
3124 | fn test() { (S {}).method()<|>; } | 3124 | fn test() { (S {}).method()<|>; } |
3125 | "#, | 3125 | "#, |
3126 | ); | 3126 | ); |
3127 | assert_eq!(t, "{unknown}"); | 3127 | assert_eq!(t, "()"); |
3128 | } | 3128 | } |
3129 | 3129 | ||
3130 | #[test] | 3130 | #[test] |
@@ -3604,11 +3604,11 @@ fn test(x: Trait, y: &Trait) -> u64 { | |||
3604 | [129; 132) 'bar': fn bar() -> {unknown} | 3604 | [129; 132) 'bar': fn bar() -> {unknown} |
3605 | [129; 134) 'bar()': {unknown} | 3605 | [129; 134) 'bar()': {unknown} |
3606 | [140; 141) 'x': {unknown} | 3606 | [140; 141) 'x': {unknown} |
3607 | [140; 147) 'x.foo()': {unknown} | 3607 | [140; 147) 'x.foo()': u64 |
3608 | [153; 154) 'y': &{unknown} | 3608 | [153; 154) 'y': &{unknown} |
3609 | [153; 160) 'y.foo()': {unknown} | 3609 | [153; 160) 'y.foo()': u64 |
3610 | [166; 167) 'z': {unknown} | 3610 | [166; 167) 'z': {unknown} |
3611 | [166; 173) 'z.foo()': {unknown} | 3611 | [166; 173) 'z.foo()': u64 |
3612 | "### | 3612 | "### |
3613 | ); | 3613 | ); |
3614 | } | 3614 | } |
diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs index 8a127efa1..0367c6560 100644 --- a/crates/ra_hir/src/ty/traits/chalk.rs +++ b/crates/ra_hir/src/ty/traits/chalk.rs | |||
@@ -356,14 +356,6 @@ fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T> { | |||
356 | } | 356 | } |
357 | } | 357 | } |
358 | 358 | ||
359 | fn is_non_enumerable_trait(db: &impl HirDatabase, trait_: Trait) -> bool { | ||
360 | let name = trait_.name(db).unwrap_or_else(crate::Name::missing).to_string(); | ||
361 | match &*name { | ||
362 | "Sized" => true, | ||
363 | _ => false, | ||
364 | } | ||
365 | } | ||
366 | |||
367 | fn convert_where_clauses( | 359 | fn convert_where_clauses( |
368 | db: &impl HirDatabase, | 360 | db: &impl HirDatabase, |
369 | def: GenericDef, | 361 | def: GenericDef, |
@@ -486,7 +478,7 @@ pub(crate) fn trait_datum_query( | |||
486 | associated_ty_ids: Vec::new(), | 478 | associated_ty_ids: Vec::new(), |
487 | where_clauses: Vec::new(), | 479 | where_clauses: Vec::new(), |
488 | flags: chalk_rust_ir::TraitFlags { | 480 | flags: chalk_rust_ir::TraitFlags { |
489 | non_enumerable: false, | 481 | non_enumerable: true, |
490 | auto: false, | 482 | auto: false, |
491 | marker: false, | 483 | marker: false, |
492 | upstream: true, | 484 | upstream: true, |
@@ -503,7 +495,7 @@ pub(crate) fn trait_datum_query( | |||
503 | let flags = chalk_rust_ir::TraitFlags { | 495 | let flags = chalk_rust_ir::TraitFlags { |
504 | auto: trait_.is_auto(db), | 496 | auto: trait_.is_auto(db), |
505 | upstream: trait_.module(db).krate(db) != Some(krate), | 497 | upstream: trait_.module(db).krate(db) != Some(krate), |
506 | non_enumerable: is_non_enumerable_trait(db, trait_), | 498 | non_enumerable: true, |
507 | // FIXME set these flags correctly | 499 | // FIXME set these flags correctly |
508 | marker: false, | 500 | marker: false, |
509 | fundamental: false, | 501 | fundamental: false, |