aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_cli/Cargo.toml5
-rw-r--r--crates/ra_hir/src/db.rs80
-rw-r--r--crates/ra_hir/src/ids.rs18
-rw-r--r--crates/ra_hir/src/lib.rs2
-rw-r--r--crates/ra_hir/src/mock.rs1
-rw-r--r--crates/ra_hir/src/nameres.rs4
-rw-r--r--crates/ra_hir/src/nameres/collector.rs17
-rw-r--r--crates/ra_hir/src/ty/traits.rs2
-rw-r--r--crates/ra_hir/src/ty/traits/chalk.rs412
-rw-r--r--crates/ra_ide_api/src/db.rs1
-rw-r--r--crates/ra_lsp_server/src/main_loop/handlers.rs35
-rw-r--r--crates/ra_prof/Cargo.toml1
-rw-r--r--crates/ra_prof/src/lib.rs33
13 files changed, 358 insertions, 253 deletions
diff --git a/crates/ra_cli/Cargo.toml b/crates/ra_cli/Cargo.toml
index 301145b5d..b10873cd8 100644
--- a/crates/ra_cli/Cargo.toml
+++ b/crates/ra_cli/Cargo.toml
@@ -16,4 +16,7 @@ ra_ide_api = { path = "../ra_ide_api" }
16ra_batch = { path = "../ra_batch" } 16ra_batch = { path = "../ra_batch" }
17ra_hir = { path = "../ra_hir" } 17ra_hir = { path = "../ra_hir" }
18ra_db = { path = "../ra_db" } 18ra_db = { path = "../ra_db" }
19ra_prof = { path = "../ra_prof" } 19
20[dependencies.ra_prof]
21path = "../ra_prof"
22# features = [ "cpuprofiler" ]
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index d8832a9de..8f4de1c85 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -20,13 +20,41 @@ use crate::{
20 lang_item::{LangItems, LangItemTarget}, type_alias::TypeAliasData, 20 lang_item::{LangItems, LangItemTarget}, type_alias::TypeAliasData,
21}; 21};
22 22
23// This database has access to source code, so queries here are not really 23/// We store all interned things in the single QueryGroup.
24// incremental. 24///
25#[salsa::query_group(AstDatabaseStorage)] 25/// This is done mainly to allow both "volatile" `AstDatabase` and "stable"
26pub trait AstDatabase: SourceDatabase { 26/// `DefDatabase` to access macros, without adding hard dependencies between the
27/// two.
28#[salsa::query_group(InternDatabaseStorage)]
29pub trait InternDatabase: SourceDatabase {
27 #[salsa::interned] 30 #[salsa::interned]
28 fn intern_macro(&self, macro_call: MacroCallLoc) -> ids::MacroCallId; 31 fn intern_macro(&self, macro_call: MacroCallLoc) -> ids::MacroCallId;
32 #[salsa::interned]
33 fn intern_function(&self, loc: ids::ItemLoc<ast::FnDef>) -> ids::FunctionId;
34 #[salsa::interned]
35 fn intern_struct(&self, loc: ids::ItemLoc<ast::StructDef>) -> ids::StructId;
36 #[salsa::interned]
37 fn intern_enum(&self, loc: ids::ItemLoc<ast::EnumDef>) -> ids::EnumId;
38 #[salsa::interned]
39 fn intern_const(&self, loc: ids::ItemLoc<ast::ConstDef>) -> ids::ConstId;
40 #[salsa::interned]
41 fn intern_static(&self, loc: ids::ItemLoc<ast::StaticDef>) -> ids::StaticId;
42 #[salsa::interned]
43 fn intern_trait(&self, loc: ids::ItemLoc<ast::TraitDef>) -> ids::TraitId;
44 #[salsa::interned]
45 fn intern_type_alias(&self, loc: ids::ItemLoc<ast::TypeAliasDef>) -> ids::TypeAliasId;
29 46
47 // Interned IDs for Chalk integration
48 #[salsa::interned]
49 fn intern_type_ctor(&self, type_ctor: TypeCtor) -> ids::TypeCtorId;
50 #[salsa::interned]
51 fn intern_impl_block(&self, impl_block: ImplBlock) -> ids::GlobalImplId;
52}
53
54/// This database has access to source code, so queries here are not really
55/// incremental.
56#[salsa::query_group(AstDatabaseStorage)]
57pub trait AstDatabase: InternDatabase {
30 #[salsa::invoke(crate::source_id::AstIdMap::ast_id_map_query)] 58 #[salsa::invoke(crate::source_id::AstIdMap::ast_id_map_query)]
31 fn ast_id_map(&self, file_id: HirFileId) -> Arc<AstIdMap>; 59 fn ast_id_map(&self, file_id: HirFileId) -> Arc<AstIdMap>;
32 #[salsa::transparent] 60 #[salsa::transparent]
@@ -40,7 +68,6 @@ pub trait AstDatabase: SourceDatabase {
40 68
41 #[salsa::invoke(crate::ids::macro_def_query)] 69 #[salsa::invoke(crate::ids::macro_def_query)]
42 fn macro_def(&self, macro_id: MacroDefId) -> Option<Arc<mbe::MacroRules>>; 70 fn macro_def(&self, macro_id: MacroDefId) -> Option<Arc<mbe::MacroRules>>;
43
44 #[salsa::invoke(crate::ids::macro_arg_query)] 71 #[salsa::invoke(crate::ids::macro_arg_query)]
45 fn macro_arg(&self, macro_call: ids::MacroCallId) -> Option<Arc<tt::Subtree>>; 72 fn macro_arg(&self, macro_call: ids::MacroCallId) -> Option<Arc<tt::Subtree>>;
46 73
@@ -51,28 +78,7 @@ pub trait AstDatabase: SourceDatabase {
51// This database uses `AstDatabase` internally, 78// This database uses `AstDatabase` internally,
52#[salsa::query_group(DefDatabaseStorage)] 79#[salsa::query_group(DefDatabaseStorage)]
53#[salsa::requires(AstDatabase)] 80#[salsa::requires(AstDatabase)]
54pub trait DefDatabase: SourceDatabase { 81pub trait DefDatabase: InternDatabase {
55 #[salsa::interned]
56 fn intern_function(&self, loc: ids::ItemLoc<ast::FnDef>) -> ids::FunctionId;
57 #[salsa::interned]
58 fn intern_struct(&self, loc: ids::ItemLoc<ast::StructDef>) -> ids::StructId;
59 #[salsa::interned]
60 fn intern_enum(&self, loc: ids::ItemLoc<ast::EnumDef>) -> ids::EnumId;
61 #[salsa::interned]
62 fn intern_const(&self, loc: ids::ItemLoc<ast::ConstDef>) -> ids::ConstId;
63 #[salsa::interned]
64 fn intern_static(&self, loc: ids::ItemLoc<ast::StaticDef>) -> ids::StaticId;
65 #[salsa::interned]
66 fn intern_trait(&self, loc: ids::ItemLoc<ast::TraitDef>) -> ids::TraitId;
67 #[salsa::interned]
68 fn intern_type_alias(&self, loc: ids::ItemLoc<ast::TypeAliasDef>) -> ids::TypeAliasId;
69
70 // Interned IDs for Chalk integration
71 #[salsa::interned]
72 fn intern_type_ctor(&self, type_ctor: TypeCtor) -> ids::TypeCtorId;
73 #[salsa::interned]
74 fn intern_impl_block(&self, impl_block: ImplBlock) -> ids::GlobalImplId;
75
76 #[salsa::invoke(crate::adt::StructData::struct_data_query)] 82 #[salsa::invoke(crate::adt::StructData::struct_data_query)]
77 fn struct_data(&self, s: Struct) -> Arc<StructData>; 83 fn struct_data(&self, s: Struct) -> Arc<StructData>;
78 84
@@ -181,6 +187,26 @@ pub trait HirDatabase: DefDatabase + AstDatabase {
181 #[salsa::volatile] 187 #[salsa::volatile]
182 fn solver(&self, krate: Crate) -> Arc<Mutex<crate::ty::traits::Solver>>; 188 fn solver(&self, krate: Crate) -> Arc<Mutex<crate::ty::traits::Solver>>;
183 189
190 #[salsa::invoke(crate::ty::traits::chalk::associated_ty_data_query)]
191 fn associated_ty_data(&self, id: chalk_ir::TypeId) -> Arc<chalk_rust_ir::AssociatedTyDatum>;
192
193 #[salsa::invoke(crate::ty::traits::chalk::trait_datum_query)]
194 fn trait_datum(
195 &self,
196 krate: Crate,
197 trait_id: chalk_ir::TraitId,
198 ) -> Arc<chalk_rust_ir::TraitDatum>;
199
200 #[salsa::invoke(crate::ty::traits::chalk::struct_datum_query)]
201 fn struct_datum(
202 &self,
203 krate: Crate,
204 struct_id: chalk_ir::StructId,
205 ) -> Arc<chalk_rust_ir::StructDatum>;
206
207 #[salsa::invoke(crate::ty::traits::chalk::impl_datum_query)]
208 fn impl_datum(&self, krate: Crate, impl_id: chalk_ir::ImplId) -> Arc<chalk_rust_ir::ImplDatum>;
209
184 #[salsa::invoke(crate::ty::traits::implements_query)] 210 #[salsa::invoke(crate::ty::traits::implements_query)]
185 fn implements( 211 fn implements(
186 &self, 212 &self,
diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs
index 033af1632..b7215ac03 100644
--- a/crates/ra_hir/src/ids.rs
+++ b/crates/ra_hir/src/ids.rs
@@ -9,7 +9,7 @@ use ra_prof::profile;
9use mbe::MacroRules; 9use mbe::MacroRules;
10 10
11use crate::{ 11use crate::{
12 Module, DefDatabase, AstId, FileAstId, AstDatabase, Source, 12 Module, DefDatabase, AstId, FileAstId, AstDatabase, Source, InternDatabase,
13}; 13};
14 14
15/// hir makes heavy use of ids: integer (u32) handlers to various things. You 15/// hir makes heavy use of ids: integer (u32) handlers to various things. You
@@ -37,7 +37,7 @@ pub struct HirFileId(HirFileIdRepr);
37impl HirFileId { 37impl HirFileId {
38 /// For macro-expansion files, returns the file original source file the 38 /// For macro-expansion files, returns the file original source file the
39 /// expansion originated from. 39 /// expansion originated from.
40 pub fn original_file(self, db: &impl AstDatabase) -> FileId { 40 pub fn original_file(self, db: &impl InternDatabase) -> FileId {
41 match self.0 { 41 match self.0 {
42 HirFileIdRepr::File(file_id) => file_id, 42 HirFileIdRepr::File(file_id) => file_id,
43 HirFileIdRepr::Macro(macro_file) => { 43 HirFileIdRepr::Macro(macro_file) => {
@@ -187,7 +187,7 @@ pub struct MacroCallLoc {
187} 187}
188 188
189impl MacroCallId { 189impl MacroCallId {
190 pub(crate) fn loc(self, db: &impl AstDatabase) -> MacroCallLoc { 190 pub(crate) fn loc(self, db: &impl InternDatabase) -> MacroCallLoc {
191 db.lookup_intern_macro(self) 191 db.lookup_intern_macro(self)
192 } 192 }
193 193
@@ -198,7 +198,7 @@ impl MacroCallId {
198} 198}
199 199
200impl MacroCallLoc { 200impl MacroCallLoc {
201 pub(crate) fn id(self, db: &impl AstDatabase) -> MacroCallId { 201 pub(crate) fn id(self, db: &impl InternDatabase) -> MacroCallId {
202 db.intern_macro(self) 202 db.intern_macro(self)
203 } 203 }
204} 204}
@@ -235,10 +235,13 @@ pub(crate) struct LocationCtx<DB> {
235 file_id: HirFileId, 235 file_id: HirFileId,
236} 236}
237 237
238impl<'a, DB: DefDatabase + AstDatabase> LocationCtx<&'a DB> { 238impl<'a, DB: DefDatabase> LocationCtx<&'a DB> {
239 pub(crate) fn new(db: &'a DB, module: Module, file_id: HirFileId) -> LocationCtx<&'a DB> { 239 pub(crate) fn new(db: &'a DB, module: Module, file_id: HirFileId) -> LocationCtx<&'a DB> {
240 LocationCtx { db, module, file_id } 240 LocationCtx { db, module, file_id }
241 } 241 }
242}
243
244impl<'a, DB: DefDatabase + AstDatabase> LocationCtx<&'a DB> {
242 pub(crate) fn to_def<N, DEF>(self, ast: &N) -> DEF 245 pub(crate) fn to_def<N, DEF>(self, ast: &N) -> DEF
243 where 246 where
244 N: AstNode, 247 N: AstNode,
@@ -257,10 +260,7 @@ pub(crate) trait AstItemDef<N: AstNode>: salsa::InternKey + Clone {
257 let item_id = items.ast_id(ast); 260 let item_id = items.ast_id(ast);
258 Self::from_ast_id(ctx, item_id) 261 Self::from_ast_id(ctx, item_id)
259 } 262 }
260 fn from_ast_id( 263 fn from_ast_id(ctx: LocationCtx<&impl DefDatabase>, ast_id: FileAstId<N>) -> Self {
261 ctx: LocationCtx<&(impl AstDatabase + DefDatabase)>,
262 ast_id: FileAstId<N>,
263 ) -> Self {
264 let loc = ItemLoc { module: ctx.module, ast_id: ast_id.with_file_id(ctx.file_id) }; 264 let loc = ItemLoc { module: ctx.module, ast_id: ast_id.with_file_id(ctx.file_id) };
265 Self::intern(ctx.db, loc) 265 Self::intern(ctx.db, loc)
266 } 266 }
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index f07a36926..5afd846f5 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -47,7 +47,7 @@ mod code_model;
47mod marks; 47mod marks;
48 48
49use crate::{ 49use crate::{
50 db::{AstDatabase, DefDatabase, HirDatabase}, 50 db::{InternDatabase, AstDatabase, DefDatabase, HirDatabase},
51 name::{AsName, KnownName}, 51 name::{AsName, KnownName},
52 source_id::{FileAstId, AstId}, 52 source_id::{FileAstId, AstId},
53 resolve::Resolver, 53 resolve::Resolver,
diff --git a/crates/ra_hir/src/mock.rs b/crates/ra_hir/src/mock.rs
index 5d38ac76c..c57dfbf01 100644
--- a/crates/ra_hir/src/mock.rs
+++ b/crates/ra_hir/src/mock.rs
@@ -15,6 +15,7 @@ pub const WORKSPACE: SourceRootId = SourceRootId(0);
15 15
16#[salsa::database( 16#[salsa::database(
17 ra_db::SourceDatabaseStorage, 17 ra_db::SourceDatabaseStorage,
18 db::InternDatabaseStorage,
18 db::AstDatabaseStorage, 19 db::AstDatabaseStorage,
19 db::DefDatabaseStorage, 20 db::DefDatabaseStorage,
20 db::HirDatabaseStorage 21 db::HirDatabaseStorage
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs
index 3532faf01..f4ca454e4 100644
--- a/crates/ra_hir/src/nameres.rs
+++ b/crates/ra_hir/src/nameres.rs
@@ -231,7 +231,9 @@ fn or(left: ItemOrMacro, right: ItemOrMacro) -> ItemOrMacro {
231 231
232impl CrateDefMap { 232impl CrateDefMap {
233 pub(crate) fn crate_def_map_query( 233 pub(crate) fn crate_def_map_query(
234 db: &(impl DefDatabase + AstDatabase), 234 // Note that this doesn't have `+ AstDatabase`!
235 // This gurantess that `CrateDefMap` is stable across reparses.
236 db: &impl DefDatabase,
235 krate: Crate, 237 krate: Crate,
236 ) -> Arc<CrateDefMap> { 238 ) -> Arc<CrateDefMap> {
237 let _p = profile("crate_def_map_query"); 239 let _p = profile("crate_def_map_query");
diff --git a/crates/ra_hir/src/nameres/collector.rs b/crates/ra_hir/src/nameres/collector.rs
index b74dc33b1..ef4d1ed70 100644
--- a/crates/ra_hir/src/nameres/collector.rs
+++ b/crates/ra_hir/src/nameres/collector.rs
@@ -7,7 +7,7 @@ use ra_syntax::ast;
7 7
8use crate::{ 8use crate::{
9 Function, Module, Struct, Union, Enum, Const, Static, Trait, TypeAlias, MacroDef, 9 Function, Module, Struct, Union, Enum, Const, Static, Trait, TypeAlias, MacroDef,
10 DefDatabase, HirFileId, Name, Path, AstDatabase, 10 DefDatabase, HirFileId, Name, Path,
11 KnownName, AstId, 11 KnownName, AstId,
12 nameres::{ 12 nameres::{
13 Resolution, PerNs, ModuleDef, ReachedFixedPoint, ResolveMode, 13 Resolution, PerNs, ModuleDef, ReachedFixedPoint, ResolveMode,
@@ -19,10 +19,7 @@ use crate::{
19 either::Either, 19 either::Either,
20}; 20};
21 21
22pub(super) fn collect_defs( 22pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> CrateDefMap {
23 db: &(impl DefDatabase + AstDatabase),
24 mut def_map: CrateDefMap,
25) -> CrateDefMap {
26 // populate external prelude 23 // populate external prelude
27 for dep in def_map.krate.dependencies(db) { 24 for dep in def_map.krate.dependencies(db) {
28 log::debug!("crate dep {:?} -> {:?}", dep.name, dep.krate); 25 log::debug!("crate dep {:?} -> {:?}", dep.name, dep.krate);
@@ -95,7 +92,7 @@ struct DefCollector<DB> {
95 92
96impl<'a, DB> DefCollector<&'a DB> 93impl<'a, DB> DefCollector<&'a DB>
97where 94where
98 DB: DefDatabase + AstDatabase, 95 DB: DefDatabase,
99{ 96{
100 fn collect(&mut self) { 97 fn collect(&mut self) {
101 let crate_graph = self.db.crate_graph(); 98 let crate_graph = self.db.crate_graph();
@@ -465,7 +462,7 @@ where
465 ModCollector { def_collector: &mut *self, file_id, module_id, raw_items: &raw_items } 462 ModCollector { def_collector: &mut *self, file_id, module_id, raw_items: &raw_items }
466 .collect(raw_items.items()); 463 .collect(raw_items.items());
467 } else { 464 } else {
468 log::error!("Too deep macro expansion: {}", macro_call_id.debug_dump(self.db)); 465 log::error!("Too deep macro expansion: {:?}", macro_call_id);
469 self.def_map.poison_macros.insert(macro_def_id); 466 self.def_map.poison_macros.insert(macro_def_id);
470 } 467 }
471 468
@@ -487,7 +484,7 @@ struct ModCollector<'a, D> {
487 484
488impl<DB> ModCollector<'_, &'_ mut DefCollector<&'_ DB>> 485impl<DB> ModCollector<'_, &'_ mut DefCollector<&'_ DB>>
489where 486where
490 DB: DefDatabase + AstDatabase, 487 DB: DefDatabase,
491{ 488{
492 fn collect(&mut self, items: &[raw::RawItem]) { 489 fn collect(&mut self, items: &[raw::RawItem]) {
493 for item in items { 490 for item in items {
@@ -632,7 +629,7 @@ fn is_macro_rules(path: &Path) -> bool {
632} 629}
633 630
634fn resolve_submodule( 631fn resolve_submodule(
635 db: &(impl DefDatabase + AstDatabase), 632 db: &impl DefDatabase,
636 file_id: HirFileId, 633 file_id: HirFileId,
637 name: &Name, 634 name: &Name,
638 is_root: bool, 635 is_root: bool,
@@ -675,7 +672,7 @@ mod tests {
675 use rustc_hash::FxHashSet; 672 use rustc_hash::FxHashSet;
676 673
677 fn do_collect_defs( 674 fn do_collect_defs(
678 db: &(impl DefDatabase + AstDatabase), 675 db: &impl DefDatabase,
679 def_map: CrateDefMap, 676 def_map: CrateDefMap,
680 monitor: MacroStackMonitor, 677 monitor: MacroStackMonitor,
681 ) -> CrateDefMap { 678 ) -> CrateDefMap {
diff --git a/crates/ra_hir/src/ty/traits.rs b/crates/ra_hir/src/ty/traits.rs
index 9a6349d4b..69c03a36c 100644
--- a/crates/ra_hir/src/ty/traits.rs
+++ b/crates/ra_hir/src/ty/traits.rs
@@ -12,7 +12,7 @@ use super::{TraitRef, Ty, Canonical, ProjectionTy};
12 12
13use self::chalk::{ToChalk, from_chalk}; 13use self::chalk::{ToChalk, from_chalk};
14 14
15mod chalk; 15pub(crate) mod chalk;
16 16
17pub(crate) type Solver = chalk_solve::Solver; 17pub(crate) type Solver = chalk_solve::Solver;
18 18
diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs
index 5105588ee..4ceb8b70b 100644
--- a/crates/ra_hir/src/ty/traits/chalk.rs
+++ b/crates/ra_hir/src/ty/traits/chalk.rs
@@ -10,7 +10,7 @@ use test_utils::tested_by;
10use ra_db::salsa::{InternId, InternKey}; 10use ra_db::salsa::{InternId, InternKey};
11 11
12use crate::{ 12use crate::{
13 Trait, HasGenericParams, ImplBlock, 13 Trait, HasGenericParams, ImplBlock, Crate,
14 db::HirDatabase, 14 db::HirDatabase,
15 ty::{TraitRef, Ty, ApplicationTy, TypeCtor, Substs, GenericPredicate, CallableDef, ProjectionTy}, 15 ty::{TraitRef, Ty, ApplicationTy, TypeCtor, Substs, GenericPredicate, CallableDef, ProjectionTy},
16 ty::display::HirDisplay, 16 ty::display::HirDisplay,
@@ -256,204 +256,16 @@ where
256 DB: HirDatabase, 256 DB: HirDatabase,
257{ 257{
258 fn associated_ty_data(&self, id: TypeId) -> Arc<AssociatedTyDatum> { 258 fn associated_ty_data(&self, id: TypeId) -> Arc<AssociatedTyDatum> {
259 debug!("associated_ty_data {:?}", id); 259 self.db.associated_ty_data(id)
260 let type_alias: TypeAlias = from_chalk(self.db, id);
261 let trait_ = match type_alias.container(self.db) {
262 Some(crate::Container::Trait(t)) => t,
263 _ => panic!("associated type not in trait"),
264 };
265 let generic_params = type_alias.generic_params(self.db);
266 let parameter_kinds = generic_params
267 .params_including_parent()
268 .into_iter()
269 .map(|p| chalk_ir::ParameterKind::Ty(lalrpop_intern::intern(&p.name.to_string())))
270 .collect();
271 let datum = AssociatedTyDatum {
272 trait_id: trait_.to_chalk(self.db),
273 id,
274 name: lalrpop_intern::intern(&type_alias.name(self.db).to_string()),
275 parameter_kinds,
276 // FIXME add bounds and where clauses
277 bounds: vec![],
278 where_clauses: vec![],
279 };
280 Arc::new(datum)
281 } 260 }
282 fn trait_datum(&self, trait_id: chalk_ir::TraitId) -> Arc<TraitDatum> { 261 fn trait_datum(&self, trait_id: chalk_ir::TraitId) -> Arc<TraitDatum> {
283 debug!("trait_datum {:?}", trait_id); 262 self.db.trait_datum(self.krate, trait_id)
284 if trait_id == UNKNOWN_TRAIT {
285 let trait_datum_bound = chalk_rust_ir::TraitDatumBound {
286 trait_ref: chalk_ir::TraitRef {
287 trait_id: UNKNOWN_TRAIT,
288 parameters: vec![chalk_ir::Ty::BoundVar(0).cast()],
289 },
290 associated_ty_ids: Vec::new(),
291 where_clauses: Vec::new(),
292 flags: chalk_rust_ir::TraitFlags {
293 auto: false,
294 marker: false,
295 upstream: true,
296 fundamental: false,
297 },
298 };
299 return Arc::new(TraitDatum { binders: make_binders(trait_datum_bound, 1) });
300 }
301 let trait_: Trait = from_chalk(self.db, trait_id);
302 debug!("trait {:?} = {:?}", trait_id, trait_.name(self.db));
303 let generic_params = trait_.generic_params(self.db);
304 let bound_vars = Substs::bound_vars(&generic_params);
305 let trait_ref = trait_.trait_ref(self.db).subst(&bound_vars).to_chalk(self.db);
306 let flags = chalk_rust_ir::TraitFlags {
307 auto: trait_.is_auto(self.db),
308 upstream: trait_.module(self.db).krate(self.db) != Some(self.krate),
309 // FIXME set these flags correctly
310 marker: false,
311 fundamental: false,
312 };
313 let where_clauses = convert_where_clauses(self.db, trait_.into(), &bound_vars);
314 let associated_ty_ids = trait_
315 .items(self.db)
316 .into_iter()
317 .filter_map(|trait_item| match trait_item {
318 crate::traits::TraitItem::TypeAlias(type_alias) => Some(type_alias),
319 _ => None,
320 })
321 .map(|type_alias| type_alias.to_chalk(self.db))
322 .collect();
323 let trait_datum_bound =
324 chalk_rust_ir::TraitDatumBound { trait_ref, where_clauses, flags, associated_ty_ids };
325 let trait_datum = TraitDatum { binders: make_binders(trait_datum_bound, bound_vars.len()) };
326 Arc::new(trait_datum)
327 } 263 }
328 fn struct_datum(&self, struct_id: chalk_ir::StructId) -> Arc<StructDatum> { 264 fn struct_datum(&self, struct_id: chalk_ir::StructId) -> Arc<StructDatum> {
329 debug!("struct_datum {:?}", struct_id); 265 self.db.struct_datum(self.krate, struct_id)
330 let type_ctor = from_chalk(self.db, struct_id);
331 debug!("struct {:?} = {:?}", struct_id, type_ctor);
332 // FIXME might be nicer if we can create a fake GenericParams for the TypeCtor
333 // FIXME extract this to a method on Ty
334 let (num_params, where_clauses, upstream) = match type_ctor {
335 TypeCtor::Bool
336 | TypeCtor::Char
337 | TypeCtor::Int(_)
338 | TypeCtor::Float(_)
339 | TypeCtor::Never
340 | TypeCtor::Str => (0, vec![], true),
341 TypeCtor::Slice | TypeCtor::Array | TypeCtor::RawPtr(_) | TypeCtor::Ref(_) => {
342 (1, vec![], true)
343 }
344 TypeCtor::FnPtr { num_args } => (num_args as usize + 1, vec![], true),
345 TypeCtor::Tuple { cardinality } => (cardinality as usize, vec![], true),
346 TypeCtor::FnDef(callable) => {
347 tested_by!(trait_resolution_on_fn_type);
348 let krate = match callable {
349 CallableDef::Function(f) => f.module(self.db).krate(self.db),
350 CallableDef::Struct(s) => s.module(self.db).krate(self.db),
351 CallableDef::EnumVariant(v) => {
352 v.parent_enum(self.db).module(self.db).krate(self.db)
353 }
354 };
355 let generic_def: GenericDef = match callable {
356 CallableDef::Function(f) => f.into(),
357 CallableDef::Struct(s) => s.into(),
358 CallableDef::EnumVariant(v) => v.parent_enum(self.db).into(),
359 };
360 let generic_params = generic_def.generic_params(self.db);
361 let bound_vars = Substs::bound_vars(&generic_params);
362 let where_clauses = convert_where_clauses(self.db, generic_def, &bound_vars);
363 (
364 generic_params.count_params_including_parent(),
365 where_clauses,
366 krate != Some(self.krate),
367 )
368 }
369 TypeCtor::Adt(adt) => {
370 let generic_params = adt.generic_params(self.db);
371 let bound_vars = Substs::bound_vars(&generic_params);
372 let where_clauses = convert_where_clauses(self.db, adt.into(), &bound_vars);
373 (
374 generic_params.count_params_including_parent(),
375 where_clauses,
376 adt.krate(self.db) != Some(self.krate),
377 )
378 }
379 };
380 let flags = chalk_rust_ir::StructFlags {
381 upstream,
382 // FIXME set fundamental flag correctly
383 fundamental: false,
384 };
385 let self_ty = chalk_ir::ApplicationTy {
386 name: TypeName::TypeKindId(type_ctor.to_chalk(self.db).into()),
387 parameters: (0..num_params).map(|i| chalk_ir::Ty::BoundVar(i).cast()).collect(),
388 };
389 let struct_datum_bound = chalk_rust_ir::StructDatumBound {
390 self_ty,
391 fields: Vec::new(), // FIXME add fields (only relevant for auto traits)
392 where_clauses,
393 flags,
394 };
395 let struct_datum = StructDatum { binders: make_binders(struct_datum_bound, num_params) };
396 Arc::new(struct_datum)
397 } 266 }
398 fn impl_datum(&self, impl_id: ImplId) -> Arc<ImplDatum> { 267 fn impl_datum(&self, impl_id: ImplId) -> Arc<ImplDatum> {
399 debug!("impl_datum {:?}", impl_id); 268 self.db.impl_datum(self.krate, impl_id)
400 let impl_block: ImplBlock = from_chalk(self.db, impl_id);
401 let generic_params = impl_block.generic_params(self.db);
402 let bound_vars = Substs::bound_vars(&generic_params);
403 let trait_ref = impl_block
404 .target_trait_ref(self.db)
405 .expect("FIXME handle unresolved impl block trait ref")
406 .subst(&bound_vars);
407 let impl_type = if impl_block.module().krate(self.db) == Some(self.krate) {
408 chalk_rust_ir::ImplType::Local
409 } else {
410 chalk_rust_ir::ImplType::External
411 };
412 let where_clauses = convert_where_clauses(self.db, impl_block.into(), &bound_vars);
413 let negative = impl_block.is_negative(self.db);
414 debug!(
415 "impl {:?}: {}{} where {:?}",
416 impl_id,
417 if negative { "!" } else { "" },
418 trait_ref.display(self.db),
419 where_clauses
420 );
421 let trait_ = trait_ref.trait_;
422 let trait_ref = trait_ref.to_chalk(self.db);
423 let associated_ty_values = impl_block
424 .items(self.db)
425 .into_iter()
426 .filter_map(|item| match item {
427 ImplItem::TypeAlias(t) => Some(t),
428 _ => None,
429 })
430 .filter_map(|t| {
431 let assoc_ty = trait_.associated_type_by_name(self.db, t.name(self.db))?;
432 let ty = self.db.type_for_def(t.into(), crate::Namespace::Types).subst(&bound_vars);
433 Some(chalk_rust_ir::AssociatedTyValue {
434 impl_id,
435 associated_ty_id: assoc_ty.to_chalk(self.db),
436 value: chalk_ir::Binders {
437 value: chalk_rust_ir::AssociatedTyValueBound { ty: ty.to_chalk(self.db) },
438 binders: vec![], // we don't support GATs yet
439 },
440 })
441 })
442 .collect();
443
444 let impl_datum_bound = chalk_rust_ir::ImplDatumBound {
445 trait_ref: if negative {
446 chalk_rust_ir::PolarizedTraitRef::Negative(trait_ref)
447 } else {
448 chalk_rust_ir::PolarizedTraitRef::Positive(trait_ref)
449 },
450 where_clauses,
451 associated_ty_values,
452 impl_type,
453 };
454 debug!("impl_datum: {:?}", impl_datum_bound);
455 let impl_datum = ImplDatum { binders: make_binders(impl_datum_bound, bound_vars.len()) };
456 Arc::new(impl_datum)
457 } 269 }
458 fn impls_for_trait(&self, trait_id: chalk_ir::TraitId) -> Vec<ImplId> { 270 fn impls_for_trait(&self, trait_id: chalk_ir::TraitId) -> Vec<ImplId> {
459 debug!("impls_for_trait {:?}", trait_id); 271 debug!("impls_for_trait {:?}", trait_id);
@@ -503,6 +315,220 @@ where
503 } 315 }
504} 316}
505 317
318pub(crate) fn associated_ty_data_query(
319 db: &impl HirDatabase,
320 id: TypeId,
321) -> Arc<AssociatedTyDatum> {
322 debug!("associated_ty_data {:?}", id);
323 let type_alias: TypeAlias = from_chalk(db, id);
324 let trait_ = match type_alias.container(db) {
325 Some(crate::Container::Trait(t)) => t,
326 _ => panic!("associated type not in trait"),
327 };
328 let generic_params = type_alias.generic_params(db);
329 let parameter_kinds = generic_params
330 .params_including_parent()
331 .into_iter()
332 .map(|p| chalk_ir::ParameterKind::Ty(lalrpop_intern::intern(&p.name.to_string())))
333 .collect();
334 let datum = AssociatedTyDatum {
335 trait_id: trait_.to_chalk(db),
336 id,
337 name: lalrpop_intern::intern(&type_alias.name(db).to_string()),
338 parameter_kinds,
339 // FIXME add bounds and where clauses
340 bounds: vec![],
341 where_clauses: vec![],
342 };
343 Arc::new(datum)
344}
345
346pub(crate) fn trait_datum_query(
347 db: &impl HirDatabase,
348 krate: Crate,
349 trait_id: chalk_ir::TraitId,
350) -> Arc<TraitDatum> {
351 debug!("trait_datum {:?}", trait_id);
352 if trait_id == UNKNOWN_TRAIT {
353 let trait_datum_bound = chalk_rust_ir::TraitDatumBound {
354 trait_ref: chalk_ir::TraitRef {
355 trait_id: UNKNOWN_TRAIT,
356 parameters: vec![chalk_ir::Ty::BoundVar(0).cast()],
357 },
358 associated_ty_ids: Vec::new(),
359 where_clauses: Vec::new(),
360 flags: chalk_rust_ir::TraitFlags {
361 auto: false,
362 marker: false,
363 upstream: true,
364 fundamental: false,
365 },
366 };
367 return Arc::new(TraitDatum { binders: make_binders(trait_datum_bound, 1) });
368 }
369 let trait_: Trait = from_chalk(db, trait_id);
370 debug!("trait {:?} = {:?}", trait_id, trait_.name(db));
371 let generic_params = trait_.generic_params(db);
372 let bound_vars = Substs::bound_vars(&generic_params);
373 let trait_ref = trait_.trait_ref(db).subst(&bound_vars).to_chalk(db);
374 let flags = chalk_rust_ir::TraitFlags {
375 auto: trait_.is_auto(db),
376 upstream: trait_.module(db).krate(db) != Some(krate),
377 // FIXME set these flags correctly
378 marker: false,
379 fundamental: false,
380 };
381 let where_clauses = convert_where_clauses(db, trait_.into(), &bound_vars);
382 let associated_ty_ids = trait_
383 .items(db)
384 .into_iter()
385 .filter_map(|trait_item| match trait_item {
386 crate::traits::TraitItem::TypeAlias(type_alias) => Some(type_alias),
387 _ => None,
388 })
389 .map(|type_alias| type_alias.to_chalk(db))
390 .collect();
391 let trait_datum_bound =
392 chalk_rust_ir::TraitDatumBound { trait_ref, where_clauses, flags, associated_ty_ids };
393 let trait_datum = TraitDatum { binders: make_binders(trait_datum_bound, bound_vars.len()) };
394 Arc::new(trait_datum)
395}
396
397pub(crate) fn struct_datum_query(
398 db: &impl HirDatabase,
399 krate: Crate,
400 struct_id: chalk_ir::StructId,
401) -> Arc<StructDatum> {
402 debug!("struct_datum {:?}", struct_id);
403 let type_ctor = from_chalk(db, struct_id);
404 debug!("struct {:?} = {:?}", struct_id, type_ctor);
405 // FIXME might be nicer if we can create a fake GenericParams for the TypeCtor
406 // FIXME extract this to a method on Ty
407 let (num_params, where_clauses, upstream) = match type_ctor {
408 TypeCtor::Bool
409 | TypeCtor::Char
410 | TypeCtor::Int(_)
411 | TypeCtor::Float(_)
412 | TypeCtor::Never
413 | TypeCtor::Str => (0, vec![], true),
414 TypeCtor::Slice | TypeCtor::Array | TypeCtor::RawPtr(_) | TypeCtor::Ref(_) => {
415 (1, vec![], true)
416 }
417 TypeCtor::FnPtr { num_args } => (num_args as usize + 1, vec![], true),
418 TypeCtor::Tuple { cardinality } => (cardinality as usize, vec![], true),
419 TypeCtor::FnDef(callable) => {
420 tested_by!(trait_resolution_on_fn_type);
421 let upstream = match callable {
422 CallableDef::Function(f) => f.module(db).krate(db),
423 CallableDef::Struct(s) => s.module(db).krate(db),
424 CallableDef::EnumVariant(v) => v.parent_enum(db).module(db).krate(db),
425 } != Some(krate);
426 let generic_def: GenericDef = match callable {
427 CallableDef::Function(f) => f.into(),
428 CallableDef::Struct(s) => s.into(),
429 CallableDef::EnumVariant(v) => v.parent_enum(db).into(),
430 };
431 let generic_params = generic_def.generic_params(db);
432 let bound_vars = Substs::bound_vars(&generic_params);
433 let where_clauses = convert_where_clauses(db, generic_def, &bound_vars);
434 (generic_params.count_params_including_parent(), where_clauses, upstream)
435 }
436 TypeCtor::Adt(adt) => {
437 let generic_params = adt.generic_params(db);
438 let bound_vars = Substs::bound_vars(&generic_params);
439 let where_clauses = convert_where_clauses(db, adt.into(), &bound_vars);
440 (
441 generic_params.count_params_including_parent(),
442 where_clauses,
443 adt.krate(db) != Some(krate),
444 )
445 }
446 };
447 let flags = chalk_rust_ir::StructFlags {
448 upstream,
449 // FIXME set fundamental flag correctly
450 fundamental: false,
451 };
452 let self_ty = chalk_ir::ApplicationTy {
453 name: TypeName::TypeKindId(type_ctor.to_chalk(db).into()),
454 parameters: (0..num_params).map(|i| chalk_ir::Ty::BoundVar(i).cast()).collect(),
455 };
456 let struct_datum_bound = chalk_rust_ir::StructDatumBound {
457 self_ty,
458 fields: Vec::new(), // FIXME add fields (only relevant for auto traits)
459 where_clauses,
460 flags,
461 };
462 let struct_datum = StructDatum { binders: make_binders(struct_datum_bound, num_params) };
463 Arc::new(struct_datum)
464}
465
466pub(crate) fn impl_datum_query(
467 db: &impl HirDatabase,
468 krate: Crate,
469 impl_id: ImplId,
470) -> Arc<ImplDatum> {
471 let _p = ra_prof::profile("impl_datum");
472 debug!("impl_datum {:?}", impl_id);
473 let impl_block: ImplBlock = from_chalk(db, impl_id);
474 let generic_params = impl_block.generic_params(db);
475 let bound_vars = Substs::bound_vars(&generic_params);
476 let trait_ref = impl_block
477 .target_trait_ref(db)
478 .expect("FIXME handle unresolved impl block trait ref")
479 .subst(&bound_vars);
480 let impl_type = if impl_block.module().krate(db) == Some(krate) {
481 chalk_rust_ir::ImplType::Local
482 } else {
483 chalk_rust_ir::ImplType::External
484 };
485 let where_clauses = convert_where_clauses(db, impl_block.into(), &bound_vars);
486 let negative = impl_block.is_negative(db);
487 debug!(
488 "impl {:?}: {}{} where {:?}",
489 impl_id,
490 if negative { "!" } else { "" },
491 trait_ref.display(db),
492 where_clauses
493 );
494 let trait_ = trait_ref.trait_;
495 let trait_ref = trait_ref.to_chalk(db);
496 let associated_ty_values = impl_block
497 .items(db)
498 .into_iter()
499 .filter_map(|item| match item {
500 ImplItem::TypeAlias(t) => Some(t),
501 _ => None,
502 })
503 .filter_map(|t| {
504 let assoc_ty = trait_.associated_type_by_name(db, t.name(db))?;
505 let ty = db.type_for_def(t.into(), crate::Namespace::Types).subst(&bound_vars);
506 Some(chalk_rust_ir::AssociatedTyValue {
507 impl_id,
508 associated_ty_id: assoc_ty.to_chalk(db),
509 value: chalk_ir::Binders {
510 value: chalk_rust_ir::AssociatedTyValueBound { ty: ty.to_chalk(db) },
511 binders: vec![], // we don't support GATs yet
512 },
513 })
514 })
515 .collect();
516
517 let impl_datum_bound = chalk_rust_ir::ImplDatumBound {
518 trait_ref: if negative {
519 chalk_rust_ir::PolarizedTraitRef::Negative(trait_ref)
520 } else {
521 chalk_rust_ir::PolarizedTraitRef::Positive(trait_ref)
522 },
523 where_clauses,
524 associated_ty_values,
525 impl_type,
526 };
527 debug!("impl_datum: {:?}", impl_datum_bound);
528 let impl_datum = ImplDatum { binders: make_binders(impl_datum_bound, bound_vars.len()) };
529 Arc::new(impl_datum)
530}
531
506fn id_from_chalk<T: InternKey>(chalk_id: chalk_ir::RawId) -> T { 532fn id_from_chalk<T: InternKey>(chalk_id: chalk_ir::RawId) -> T {
507 T::from_intern_id(InternId::from(chalk_id.index)) 533 T::from_intern_id(InternId::from(chalk_id.index))
508} 534}
diff --git a/crates/ra_ide_api/src/db.rs b/crates/ra_ide_api/src/db.rs
index 82b061419..cb7d30c43 100644
--- a/crates/ra_ide_api/src/db.rs
+++ b/crates/ra_ide_api/src/db.rs
@@ -14,6 +14,7 @@ use crate::{LineIndex, symbol_index::{self, SymbolsDatabase}};
14 ra_db::SourceDatabaseStorage, 14 ra_db::SourceDatabaseStorage,
15 LineIndexDatabaseStorage, 15 LineIndexDatabaseStorage,
16 symbol_index::SymbolsDatabaseStorage, 16 symbol_index::SymbolsDatabaseStorage,
17 hir::db::InternDatabaseStorage,
17 hir::db::AstDatabaseStorage, 18 hir::db::AstDatabaseStorage,
18 hir::db::DefDatabaseStorage, 19 hir::db::DefDatabaseStorage,
19 hir::db::HirDatabaseStorage 20 hir::db::HirDatabaseStorage
diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs
index 6373240d5..47222cd0a 100644
--- a/crates/ra_lsp_server/src/main_loop/handlers.rs
+++ b/crates/ra_lsp_server/src/main_loop/handlers.rs
@@ -621,17 +621,32 @@ pub fn handle_formatting(
621 621
622 let output = rustfmt.wait_with_output()?; 622 let output = rustfmt.wait_with_output()?;
623 let captured_stdout = String::from_utf8(output.stdout)?; 623 let captured_stdout = String::from_utf8(output.stdout)?;
624
624 if !output.status.success() { 625 if !output.status.success() {
625 return Err(LspError::new( 626 match output.status.code() {
626 -32900, 627 Some(1) => {
627 format!( 628 // While `rustfmt` doesn't have a specific exit code for parse errors this is the
628 r#"rustfmt exited with: 629 // likely cause exiting with 1. Most Language Servers swallow parse errors on
629 Status: {} 630 // formatting because otherwise an error is surfaced to the user on top of the
630 stdout: {}"#, 631 // syntax error diagnostics they're already receiving. This is especially jarring
631 output.status, captured_stdout, 632 // if they have format on save enabled.
632 ), 633 log::info!("rustfmt exited with status 1, assuming parse error and ignoring");
633 ) 634 return Ok(None);
634 .into()); 635 }
636 _ => {
637 // Something else happened - e.g. `rustfmt` is missing or caught a signal
638 return Err(LspError::new(
639 -32900,
640 format!(
641 r#"rustfmt exited with:
642 Status: {}
643 stdout: {}"#,
644 output.status, captured_stdout,
645 ),
646 )
647 .into());
648 }
649 }
635 } 650 }
636 651
637 Ok(Some(vec![TextEdit { 652 Ok(Some(vec![TextEdit {
diff --git a/crates/ra_prof/Cargo.toml b/crates/ra_prof/Cargo.toml
index d55af18f5..787e18385 100644
--- a/crates/ra_prof/Cargo.toml
+++ b/crates/ra_prof/Cargo.toml
@@ -9,3 +9,4 @@ publish = false
9once_cell = "0.2.0" 9once_cell = "0.2.0"
10itertools = "0.8.0" 10itertools = "0.8.0"
11backtrace = "0.3.28" 11backtrace = "0.3.28"
12cpuprofiler = { version = "0.0.3", optional = true }
diff --git a/crates/ra_prof/src/lib.rs b/crates/ra_prof/src/lib.rs
index de67b4031..1e8d780ab 100644
--- a/crates/ra_prof/src/lib.rs
+++ b/crates/ra_prof/src/lib.rs
@@ -255,6 +255,39 @@ impl Drop for Scope {
255 } 255 }
256} 256}
257 257
258/// A wrapper around https://github.com/AtheMathmo/cpuprofiler
259///
260/// It can be used to capture sampling profiles of sections of code.
261/// It is not exactly out-of-the-box, as it relies on gperftools.
262/// See the docs for the crate for more!
263#[derive(Debug)]
264pub struct CpuProfiler {
265 _private: (),
266}
267
268pub fn cpu_profiler() -> CpuProfiler {
269 #[cfg(feature = "cpuprofiler")]
270 {
271 cpuprofiler::PROFILER.lock().unwrap().start("./out.profile").unwrap();
272 }
273
274 #[cfg(not(feature = "cpuprofiler"))]
275 {
276 eprintln!("cpuprofiler feature is disabled")
277 }
278
279 CpuProfiler { _private: () }
280}
281
282impl Drop for CpuProfiler {
283 fn drop(&mut self) {
284 #[cfg(feature = "cpuprofiler")]
285 {
286 cpuprofiler::PROFILER.lock().unwrap().stop().unwrap();
287 }
288 }
289}
290
258#[cfg(test)] 291#[cfg(test)]
259mod tests { 292mod tests {
260 use super::*; 293 use super::*;