aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_db/src/cancellation.rs2
-rw-r--r--crates/ra_db/src/lib.rs2
-rw-r--r--crates/ra_hir/src/adt.rs5
-rw-r--r--crates/ra_hir/src/code_model_api.rs11
-rw-r--r--crates/ra_hir/src/code_model_impl/module.rs9
-rw-r--r--crates/ra_hir/src/db.rs10
-rw-r--r--crates/ra_hir/src/lib.rs9
-rw-r--r--crates/ra_hir/src/ty.rs234
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs39
-rw-r--r--crates/ra_hir/src/ty/tests.rs6
-rw-r--r--crates/ra_ide_api/src/call_info.rs16
-rw-r--r--crates/ra_ide_api/src/completion.rs19
-rw-r--r--crates/ra_ide_api/src/completion/complete_dot.rs30
-rw-r--r--crates/ra_ide_api/src/completion/complete_path.rs10
-rw-r--r--crates/ra_ide_api/src/completion/complete_scope.rs12
-rw-r--r--crates/ra_ide_api/src/completion/completion_context.rs9
-rw-r--r--crates/ra_ide_api/src/goto_definition.rs35
-rw-r--r--crates/ra_ide_api/src/hover.rs50
-rw-r--r--crates/ra_ide_api/src/imp.rs51
-rw-r--r--crates/ra_ide_api/src/lib.rs31
-rw-r--r--crates/ra_ide_api/src/parent_module.rs11
-rw-r--r--crates/ra_ide_api/src/runnables.rs9
22 files changed, 254 insertions, 356 deletions
diff --git a/crates/ra_db/src/cancellation.rs b/crates/ra_db/src/cancellation.rs
index 32a268553..439080075 100644
--- a/crates/ra_db/src/cancellation.rs
+++ b/crates/ra_db/src/cancellation.rs
@@ -21,8 +21,6 @@ pub struct Canceled {
21 _private: (), 21 _private: (),
22} 22}
23 23
24pub type Cancelable<T> = Result<T, Canceled>;
25
26impl Canceled { 24impl Canceled {
27 pub(crate) fn new() -> Canceled { 25 pub(crate) fn new() -> Canceled {
28 Canceled { _private: () } 26 Canceled { _private: () }
diff --git a/crates/ra_db/src/lib.rs b/crates/ra_db/src/lib.rs
index 8473fc050..89113e7a6 100644
--- a/crates/ra_db/src/lib.rs
+++ b/crates/ra_db/src/lib.rs
@@ -10,7 +10,7 @@ use std::panic;
10use ra_syntax::{TextUnit, TextRange, SourceFile, TreeArc}; 10use ra_syntax::{TextUnit, TextRange, SourceFile, TreeArc};
11 11
12pub use crate::{ 12pub use crate::{
13 cancellation::{Canceled, Cancelable}, 13 cancellation::Canceled,
14 syntax_ptr::LocalSyntaxPtr, 14 syntax_ptr::LocalSyntaxPtr,
15 input::{ 15 input::{
16 FilesDatabase, FileId, CrateId, SourceRoot, SourceRootId, CrateGraph, Dependency, 16 FilesDatabase, FileId, CrateId, SourceRoot, SourceRootId, CrateGraph, Dependency,
diff --git a/crates/ra_hir/src/adt.rs b/crates/ra_hir/src/adt.rs
index 57d112f74..d87fe7049 100644
--- a/crates/ra_hir/src/adt.rs
+++ b/crates/ra_hir/src/adt.rs
@@ -1,6 +1,5 @@
1use std::sync::Arc; 1use std::sync::Arc;
2 2
3use ra_db::Cancelable;
4use ra_syntax::{ 3use ra_syntax::{
5 SyntaxNode, 4 SyntaxNode,
6 ast::{self, NameOwner, StructFlavor, AstNode} 5 ast::{self, NameOwner, StructFlavor, AstNode}
@@ -18,8 +17,8 @@ impl Struct {
18 Struct { def_id } 17 Struct { def_id }
19 } 18 }
20 19
21 pub(crate) fn variant_data(&self, db: &impl HirDatabase) -> Cancelable<Arc<VariantData>> { 20 pub(crate) fn variant_data(&self, db: &impl HirDatabase) -> Arc<VariantData> {
22 Ok(db.struct_data(self.def_id).variant_data.clone()) 21 db.struct_data(self.def_id).variant_data.clone()
23 } 22 }
24} 23}
25 24
diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs
index 7ccd29e2f..0cf7deac9 100644
--- a/crates/ra_hir/src/code_model_api.rs
+++ b/crates/ra_hir/src/code_model_api.rs
@@ -1,7 +1,7 @@
1use std::sync::Arc; 1use std::sync::Arc;
2 2
3use relative_path::RelativePathBuf; 3use relative_path::RelativePathBuf;
4use ra_db::{CrateId, Cancelable, FileId}; 4use ra_db::{CrateId, FileId};
5use ra_syntax::{ast, TreeArc, SyntaxNode}; 5use ra_syntax::{ast, TreeArc, SyntaxNode};
6 6
7use crate::{ 7use crate::{
@@ -142,10 +142,7 @@ impl Module {
142 self.resolve_path_impl(db, path) 142 self.resolve_path_impl(db, path)
143 } 143 }
144 144
145 pub fn problems( 145 pub fn problems(&self, db: &impl HirDatabase) -> Vec<(TreeArc<SyntaxNode>, Problem)> {
146 &self,
147 db: &impl HirDatabase,
148 ) -> Cancelable<Vec<(TreeArc<SyntaxNode>, Problem)>> {
149 self.problems_impl(db) 146 self.problems_impl(db)
150 } 147 }
151} 148}
@@ -160,7 +157,7 @@ impl StructField {
160 pub fn name(&self) -> &Name { 157 pub fn name(&self) -> &Name {
161 &self.name 158 &self.name
162 } 159 }
163 pub fn ty(&self, db: &impl HirDatabase) -> Cancelable<Option<Ty>> { 160 pub fn ty(&self, db: &impl HirDatabase) -> Option<Ty> {
164 db.type_for_field(self.struct_.def_id, self.name.clone()) 161 db.type_for_field(self.struct_.def_id, self.name.clone())
165 } 162 }
166} 163}
@@ -318,7 +315,7 @@ impl Function {
318 db.fn_signature(self.def_id) 315 db.fn_signature(self.def_id)
319 } 316 }
320 317
321 pub fn infer(&self, db: &impl HirDatabase) -> Cancelable<Arc<InferenceResult>> { 318 pub fn infer(&self, db: &impl HirDatabase) -> Arc<InferenceResult> {
322 db.infer(self.def_id) 319 db.infer(self.def_id)
323 } 320 }
324} 321}
diff --git a/crates/ra_hir/src/code_model_impl/module.rs b/crates/ra_hir/src/code_model_impl/module.rs
index 04301ae53..a5c032d69 100644
--- a/crates/ra_hir/src/code_model_impl/module.rs
+++ b/crates/ra_hir/src/code_model_impl/module.rs
@@ -1,4 +1,4 @@
1use ra_db::{Cancelable, SourceRootId, FileId}; 1use ra_db::{SourceRootId, FileId};
2use ra_syntax::{ast, SyntaxNode, AstNode, TreeArc}; 2use ra_syntax::{ast, SyntaxNode, AstNode, TreeArc};
3 3
4use crate::{ 4use crate::{
@@ -176,12 +176,9 @@ impl Module {
176 curr_per_ns 176 curr_per_ns
177 } 177 }
178 178
179 pub fn problems_impl( 179 pub fn problems_impl(&self, db: &impl HirDatabase) -> Vec<(TreeArc<SyntaxNode>, Problem)> {
180 &self,
181 db: &impl HirDatabase,
182 ) -> Cancelable<Vec<(TreeArc<SyntaxNode>, Problem)>> {
183 let loc = self.def_id.loc(db); 180 let loc = self.def_id.loc(db);
184 let module_tree = db.module_tree(loc.source_root_id); 181 let module_tree = db.module_tree(loc.source_root_id);
185 Ok(loc.module_id.problems(&module_tree, db)) 182 loc.module_id.problems(&module_tree, db)
186 } 183 }
187} 184}
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index 161a5e714..0a0994f5f 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -1,7 +1,7 @@
1use std::sync::Arc; 1use std::sync::Arc;
2 2
3use ra_syntax::{SyntaxNode, TreeArc, SourceFile}; 3use ra_syntax::{SyntaxNode, TreeArc, SourceFile};
4use ra_db::{SourceRootId, LocationIntener, SyntaxDatabase, Cancelable}; 4use ra_db::{SourceRootId, LocationIntener, SyntaxDatabase};
5 5
6use crate::{ 6use crate::{
7 DefLoc, DefId, MacroCallLoc, MacroCallId, Name, HirFileId, 7 DefLoc, DefId, MacroCallLoc, MacroCallId, Name, HirFileId,
@@ -52,17 +52,17 @@ pub trait HirDatabase: SyntaxDatabase
52 use fn crate::adt::EnumVariantData::enum_variant_data_query; 52 use fn crate::adt::EnumVariantData::enum_variant_data_query;
53 } 53 }
54 54
55 fn infer(def_id: DefId) -> Cancelable<Arc<InferenceResult>> { 55 fn infer(def_id: DefId) -> Arc<InferenceResult> {
56 type InferQuery; 56 type InferQuery;
57 use fn crate::ty::infer; 57 use fn crate::ty::infer;
58 } 58 }
59 59
60 fn type_for_def(def_id: DefId) -> Cancelable<Ty> { 60 fn type_for_def(def_id: DefId) -> Ty {
61 type TypeForDefQuery; 61 type TypeForDefQuery;
62 use fn crate::ty::type_for_def; 62 use fn crate::ty::type_for_def;
63 } 63 }
64 64
65 fn type_for_field(def_id: DefId, field: Name) -> Cancelable<Option<Ty>> { 65 fn type_for_field(def_id: DefId, field: Name) -> Option<Ty> {
66 type TypeForFieldQuery; 66 type TypeForFieldQuery;
67 use fn crate::ty::type_for_field; 67 use fn crate::ty::type_for_field;
68 } 68 }
@@ -102,7 +102,7 @@ pub trait HirDatabase: SyntaxDatabase
102 use fn crate::impl_block::impls_in_module; 102 use fn crate::impl_block::impls_in_module;
103 } 103 }
104 104
105 fn impls_in_crate(krate: Crate) -> Cancelable<Arc<CrateImplBlocks>> { 105 fn impls_in_crate(krate: Crate) -> Arc<CrateImplBlocks> {
106 type ImplsInCrateQuery; 106 type ImplsInCrateQuery;
107 use fn crate::ty::method_resolution::CrateImplBlocks::impls_in_crate_query; 107 use fn crate::ty::method_resolution::CrateImplBlocks::impls_in_crate_query;
108 } 108 }
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index 45dda4f7f..ef7d049ee 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -5,15 +5,6 @@
5//! to a particular crate instance. That is, it has cfg flags and features 5//! to a particular crate instance. That is, it has cfg flags and features
6//! applied. So, the relation between syntax and HIR is many-to-one. 6//! applied. So, the relation between syntax and HIR is many-to-one.
7 7
8macro_rules! ctry {
9 ($expr:expr) => {
10 match $expr {
11 None => return Ok(None),
12 Some(it) => it,
13 }
14 };
15}
16
17pub mod db; 8pub mod db;
18#[cfg(test)] 9#[cfg(test)]
19mod mock; 10mod mock;
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index e5f8ffc2e..dbbbce795 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -30,8 +30,6 @@ use ra_arena::map::ArenaMap;
30use join_to_string::join; 30use join_to_string::join;
31use rustc_hash::FxHashMap; 31use rustc_hash::FxHashMap;
32 32
33use ra_db::Cancelable;
34
35use crate::{ 33use crate::{
36 Def, DefId, Module, Function, Struct, Enum, EnumVariant, Path, Name, ImplBlock, 34 Def, DefId, Module, Function, Struct, Enum, EnumVariant, Path, Name, ImplBlock,
37 FnSignature, FnScopes, 35 FnSignature, FnScopes,
@@ -41,14 +39,6 @@ use crate::{
41 expr::{Body, Expr, Literal, ExprId, PatId, UnaryOp, BinaryOp, Statement}, 39 expr::{Body, Expr, Literal, ExprId, PatId, UnaryOp, BinaryOp, Statement},
42}; 40};
43 41
44fn transpose<T>(x: Cancelable<Option<T>>) -> Option<Cancelable<T>> {
45 match x {
46 Ok(Some(t)) => Some(Ok(t)),
47 Ok(None) => None,
48 Err(e) => Some(Err(e)),
49 }
50}
51
52/// The ID of a type variable. 42/// The ID of a type variable.
53#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] 43#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
54pub struct TypeVarId(u32); 44pub struct TypeVarId(u32);
@@ -271,28 +261,28 @@ impl Ty {
271 module: &Module, 261 module: &Module,
272 impl_block: Option<&ImplBlock>, 262 impl_block: Option<&ImplBlock>,
273 type_ref: &TypeRef, 263 type_ref: &TypeRef,
274 ) -> Cancelable<Self> { 264 ) -> Self {
275 Ok(match type_ref { 265 match type_ref {
276 TypeRef::Never => Ty::Never, 266 TypeRef::Never => Ty::Never,
277 TypeRef::Tuple(inner) => { 267 TypeRef::Tuple(inner) => {
278 let inner_tys = inner 268 let inner_tys = inner
279 .iter() 269 .iter()
280 .map(|tr| Ty::from_hir(db, module, impl_block, tr)) 270 .map(|tr| Ty::from_hir(db, module, impl_block, tr))
281 .collect::<Cancelable<Vec<_>>>()?; 271 .collect::<Vec<_>>();
282 Ty::Tuple(inner_tys.into()) 272 Ty::Tuple(inner_tys.into())
283 } 273 }
284 TypeRef::Path(path) => Ty::from_hir_path(db, module, impl_block, path)?, 274 TypeRef::Path(path) => Ty::from_hir_path(db, module, impl_block, path),
285 TypeRef::RawPtr(inner, mutability) => { 275 TypeRef::RawPtr(inner, mutability) => {
286 let inner_ty = Ty::from_hir(db, module, impl_block, inner)?; 276 let inner_ty = Ty::from_hir(db, module, impl_block, inner);
287 Ty::RawPtr(Arc::new(inner_ty), *mutability) 277 Ty::RawPtr(Arc::new(inner_ty), *mutability)
288 } 278 }
289 TypeRef::Array(_inner) => Ty::Unknown, // TODO 279 TypeRef::Array(_inner) => Ty::Unknown, // TODO
290 TypeRef::Slice(inner) => { 280 TypeRef::Slice(inner) => {
291 let inner_ty = Ty::from_hir(db, module, impl_block, inner)?; 281 let inner_ty = Ty::from_hir(db, module, impl_block, inner);
292 Ty::Slice(Arc::new(inner_ty)) 282 Ty::Slice(Arc::new(inner_ty))
293 } 283 }
294 TypeRef::Reference(inner, mutability) => { 284 TypeRef::Reference(inner, mutability) => {
295 let inner_ty = Ty::from_hir(db, module, impl_block, inner)?; 285 let inner_ty = Ty::from_hir(db, module, impl_block, inner);
296 Ty::Ref(Arc::new(inner_ty), *mutability) 286 Ty::Ref(Arc::new(inner_ty), *mutability)
297 } 287 }
298 TypeRef::Placeholder => Ty::Unknown, 288 TypeRef::Placeholder => Ty::Unknown,
@@ -300,7 +290,7 @@ impl Ty {
300 let mut inner_tys = params 290 let mut inner_tys = params
301 .iter() 291 .iter()
302 .map(|tr| Ty::from_hir(db, module, impl_block, tr)) 292 .map(|tr| Ty::from_hir(db, module, impl_block, tr))
303 .collect::<Cancelable<Vec<_>>>()?; 293 .collect::<Vec<_>>();
304 let return_ty = inner_tys 294 let return_ty = inner_tys
305 .pop() 295 .pop()
306 .expect("TypeRef::Fn should always have at least return type"); 296 .expect("TypeRef::Fn should always have at least return type");
@@ -311,7 +301,7 @@ impl Ty {
311 Ty::FnPtr(Arc::new(sig)) 301 Ty::FnPtr(Arc::new(sig))
312 } 302 }
313 TypeRef::Error => Ty::Unknown, 303 TypeRef::Error => Ty::Unknown,
314 }) 304 }
315 } 305 }
316 306
317 pub(crate) fn from_hir_opt( 307 pub(crate) fn from_hir_opt(
@@ -319,10 +309,8 @@ impl Ty {
319 module: &Module, 309 module: &Module,
320 impl_block: Option<&ImplBlock>, 310 impl_block: Option<&ImplBlock>,
321 type_ref: Option<&TypeRef>, 311 type_ref: Option<&TypeRef>,
322 ) -> Cancelable<Self> { 312 ) -> Self {
323 type_ref 313 type_ref.map_or(Ty::Unknown, |t| Ty::from_hir(db, module, impl_block, t))
324 .map(|t| Ty::from_hir(db, module, impl_block, t))
325 .unwrap_or(Ok(Ty::Unknown))
326 } 314 }
327 315
328 pub(crate) fn from_hir_path( 316 pub(crate) fn from_hir_path(
@@ -330,19 +318,19 @@ impl Ty {
330 module: &Module, 318 module: &Module,
331 impl_block: Option<&ImplBlock>, 319 impl_block: Option<&ImplBlock>,
332 path: &Path, 320 path: &Path,
333 ) -> Cancelable<Self> { 321 ) -> Self {
334 if let Some(name) = path.as_ident() { 322 if let Some(name) = path.as_ident() {
335 if let Some(int_ty) = primitive::UncertainIntTy::from_name(name) { 323 if let Some(int_ty) = primitive::UncertainIntTy::from_name(name) {
336 return Ok(Ty::Int(int_ty)); 324 return Ty::Int(int_ty);
337 } else if let Some(float_ty) = primitive::UncertainFloatTy::from_name(name) { 325 } else if let Some(float_ty) = primitive::UncertainFloatTy::from_name(name) {
338 return Ok(Ty::Float(float_ty)); 326 return Ty::Float(float_ty);
339 } else if name.as_known_name() == Some(KnownName::SelfType) { 327 } else if name.as_known_name() == Some(KnownName::SelfType) {
340 return Ty::from_hir_opt(db, module, None, impl_block.map(|i| i.target_type())); 328 return Ty::from_hir_opt(db, module, None, impl_block.map(|i| i.target_type()));
341 } else if let Some(known) = name.as_known_name() { 329 } else if let Some(known) = name.as_known_name() {
342 match known { 330 match known {
343 KnownName::Bool => return Ok(Ty::Bool), 331 KnownName::Bool => return Ty::Bool,
344 KnownName::Char => return Ok(Ty::Char), 332 KnownName::Char => return Ty::Char,
345 KnownName::Str => return Ok(Ty::Str), 333 KnownName::Str => return Ty::Str,
346 _ => {} 334 _ => {}
347 } 335 }
348 } 336 }
@@ -352,10 +340,9 @@ impl Ty {
352 let resolved = if let Some(r) = module.resolve_path(db, path).take_types() { 340 let resolved = if let Some(r) = module.resolve_path(db, path).take_types() {
353 r 341 r
354 } else { 342 } else {
355 return Ok(Ty::Unknown); 343 return Ty::Unknown;
356 }; 344 };
357 let ty = db.type_for_def(resolved)?; 345 db.type_for_def(resolved)
358 Ok(ty)
359 } 346 }
360 347
361 pub fn unit() -> Self { 348 pub fn unit() -> Self {
@@ -445,7 +432,7 @@ impl fmt::Display for Ty {
445 432
446/// Compute the declared type of a function. This should not need to look at the 433/// Compute the declared type of a function. This should not need to look at the
447/// function body. 434/// function body.
448fn type_for_fn(db: &impl HirDatabase, f: Function) -> Cancelable<Ty> { 435fn type_for_fn(db: &impl HirDatabase, f: Function) -> Ty {
449 let signature = f.signature(db); 436 let signature = f.signature(db);
450 let module = f.module(db); 437 let module = f.module(db);
451 let impl_block = f.impl_block(db); 438 let impl_block = f.impl_block(db);
@@ -454,38 +441,38 @@ fn type_for_fn(db: &impl HirDatabase, f: Function) -> Cancelable<Ty> {
454 .params() 441 .params()
455 .iter() 442 .iter()
456 .map(|tr| Ty::from_hir(db, &module, impl_block.as_ref(), tr)) 443 .map(|tr| Ty::from_hir(db, &module, impl_block.as_ref(), tr))
457 .collect::<Cancelable<Vec<_>>>()?; 444 .collect::<Vec<_>>();
458 let output = Ty::from_hir(db, &module, impl_block.as_ref(), signature.ret_type())?; 445 let output = Ty::from_hir(db, &module, impl_block.as_ref(), signature.ret_type());
459 let sig = FnSig { input, output }; 446 let sig = FnSig { input, output };
460 Ok(Ty::FnPtr(Arc::new(sig))) 447 Ty::FnPtr(Arc::new(sig))
461} 448}
462 449
463fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Cancelable<Ty> { 450fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty {
464 Ok(Ty::Adt { 451 Ty::Adt {
465 def_id: s.def_id(), 452 def_id: s.def_id(),
466 name: s.name(db).unwrap_or_else(Name::missing), 453 name: s.name(db).unwrap_or_else(Name::missing),
467 }) 454 }
468} 455}
469 456
470pub(crate) fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Cancelable<Ty> { 457pub(crate) fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Ty {
471 Ok(Ty::Adt { 458 Ty::Adt {
472 def_id: s.def_id(), 459 def_id: s.def_id(),
473 name: s.name(db).unwrap_or_else(Name::missing), 460 name: s.name(db).unwrap_or_else(Name::missing),
474 }) 461 }
475} 462}
476 463
477pub(crate) fn type_for_enum_variant(db: &impl HirDatabase, ev: EnumVariant) -> Cancelable<Ty> { 464pub(crate) fn type_for_enum_variant(db: &impl HirDatabase, ev: EnumVariant) -> Ty {
478 let enum_parent = ev.parent_enum(db); 465 let enum_parent = ev.parent_enum(db);
479 466
480 type_for_enum(db, enum_parent) 467 type_for_enum(db, enum_parent)
481} 468}
482 469
483pub(super) fn type_for_def(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Ty> { 470pub(super) fn type_for_def(db: &impl HirDatabase, def_id: DefId) -> Ty {
484 let def = def_id.resolve(db); 471 let def = def_id.resolve(db);
485 match def { 472 match def {
486 Def::Module(..) => { 473 Def::Module(..) => {
487 log::debug!("trying to get type for module {:?}", def_id); 474 log::debug!("trying to get type for module {:?}", def_id);
488 Ok(Ty::Unknown) 475 Ty::Unknown
489 } 476 }
490 Def::Function(f) => type_for_fn(db, f), 477 Def::Function(f) => type_for_fn(db, f),
491 Def::Struct(s) => type_for_struct(db, s), 478 Def::Struct(s) => type_for_struct(db, s),
@@ -497,19 +484,15 @@ pub(super) fn type_for_def(db: &impl HirDatabase, def_id: DefId) -> Cancelable<T
497 def_id, 484 def_id,
498 def 485 def
499 ); 486 );
500 Ok(Ty::Unknown) 487 Ty::Unknown
501 } 488 }
502 } 489 }
503} 490}
504 491
505pub(super) fn type_for_field( 492pub(super) fn type_for_field(db: &impl HirDatabase, def_id: DefId, field: Name) -> Option<Ty> {
506 db: &impl HirDatabase,
507 def_id: DefId,
508 field: Name,
509) -> Cancelable<Option<Ty>> {
510 let def = def_id.resolve(db); 493 let def = def_id.resolve(db);
511 let variant_data = match def { 494 let variant_data = match def {
512 Def::Struct(s) => s.variant_data(db)?, 495 Def::Struct(s) => s.variant_data(db),
513 Def::EnumVariant(ev) => ev.variant_data(db), 496 Def::EnumVariant(ev) => ev.variant_data(db),
514 // TODO: unions 497 // TODO: unions
515 _ => panic!( 498 _ => panic!(
@@ -519,13 +502,8 @@ pub(super) fn type_for_field(
519 }; 502 };
520 let module = def_id.module(db); 503 let module = def_id.module(db);
521 let impl_block = def_id.impl_block(db); 504 let impl_block = def_id.impl_block(db);
522 let type_ref = ctry!(variant_data.get_field_type_ref(&field)); 505 let type_ref = variant_data.get_field_type_ref(&field)?;
523 Ok(Some(Ty::from_hir( 506 Some(Ty::from_hir(db, &module, impl_block.as_ref(), &type_ref))
524 db,
525 &module,
526 impl_block.as_ref(),
527 &type_ref,
528 )?))
529} 507}
530 508
531/// The result of type inference: A mapping from expressions and patterns to types. 509/// The result of type inference: A mapping from expressions and patterns to types.
@@ -702,7 +680,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
702 self.type_of_pat.insert(pat, ty); 680 self.type_of_pat.insert(pat, ty);
703 } 681 }
704 682
705 fn make_ty(&self, type_ref: &TypeRef) -> Cancelable<Ty> { 683 fn make_ty(&self, type_ref: &TypeRef) -> Ty {
706 Ty::from_hir(self.db, &self.module, self.impl_block.as_ref(), type_ref) 684 Ty::from_hir(self.db, &self.module, self.impl_block.as_ref(), type_ref)
707 } 685 }
708 686
@@ -848,49 +826,49 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
848 }) 826 })
849 } 827 }
850 828
851 fn infer_path_expr(&mut self, expr: ExprId, path: &Path) -> Cancelable<Option<Ty>> { 829 fn infer_path_expr(&mut self, expr: ExprId, path: &Path) -> Option<Ty> {
852 if path.is_ident() || path.is_self() { 830 if path.is_ident() || path.is_self() {
853 // resolve locally 831 // resolve locally
854 let name = path.as_ident().cloned().unwrap_or_else(Name::self_param); 832 let name = path.as_ident().cloned().unwrap_or_else(Name::self_param);
855 if let Some(scope_entry) = self.scopes.resolve_local_name(expr, name) { 833 if let Some(scope_entry) = self.scopes.resolve_local_name(expr, name) {
856 let ty = ctry!(self.type_of_pat.get(scope_entry.pat())); 834 let ty = self.type_of_pat.get(scope_entry.pat())?;
857 let ty = self.resolve_ty_as_possible(ty.clone()); 835 let ty = self.resolve_ty_as_possible(ty.clone());
858 return Ok(Some(ty)); 836 return Some(ty);
859 }; 837 };
860 }; 838 };
861 839
862 // resolve in module 840 // resolve in module
863 let resolved = ctry!(self.module.resolve_path(self.db, &path).take_values()); 841 let resolved = self.module.resolve_path(self.db, &path).take_values()?;
864 let ty = self.db.type_for_def(resolved)?; 842 let ty = self.db.type_for_def(resolved);
865 let ty = self.insert_type_vars(ty); 843 let ty = self.insert_type_vars(ty);
866 Ok(Some(ty)) 844 Some(ty)
867 } 845 }
868 846
869 fn resolve_variant(&self, path: Option<&Path>) -> Cancelable<(Ty, Option<DefId>)> { 847 fn resolve_variant(&self, path: Option<&Path>) -> (Ty, Option<DefId>) {
870 let path = if let Some(path) = path { 848 let path = if let Some(path) = path {
871 path 849 path
872 } else { 850 } else {
873 return Ok((Ty::Unknown, None)); 851 return (Ty::Unknown, None);
874 }; 852 };
875 let def_id = if let Some(def_id) = self.module.resolve_path(self.db, &path).take_types() { 853 let def_id = if let Some(def_id) = self.module.resolve_path(self.db, &path).take_types() {
876 def_id 854 def_id
877 } else { 855 } else {
878 return Ok((Ty::Unknown, None)); 856 return (Ty::Unknown, None);
879 }; 857 };
880 Ok(match def_id.resolve(self.db) { 858 match def_id.resolve(self.db) {
881 Def::Struct(s) => { 859 Def::Struct(s) => {
882 let ty = type_for_struct(self.db, s)?; 860 let ty = type_for_struct(self.db, s);
883 (ty, Some(def_id)) 861 (ty, Some(def_id))
884 } 862 }
885 Def::EnumVariant(ev) => { 863 Def::EnumVariant(ev) => {
886 let ty = type_for_enum_variant(self.db, ev)?; 864 let ty = type_for_enum_variant(self.db, ev);
887 (ty, Some(def_id)) 865 (ty, Some(def_id))
888 } 866 }
889 _ => (Ty::Unknown, None), 867 _ => (Ty::Unknown, None),
890 }) 868 }
891 } 869 }
892 870
893 fn infer_expr(&mut self, expr: ExprId, expected: &Expectation) -> Cancelable<Ty> { 871 fn infer_expr(&mut self, expr: ExprId, expected: &Expectation) -> Ty {
894 let body = Arc::clone(&self.body); // avoid borrow checker problem 872 let body = Arc::clone(&self.body); // avoid borrow checker problem
895 let ty = match &body[expr] { 873 let ty = match &body[expr] {
896 Expr::Missing => Ty::Unknown, 874 Expr::Missing => Ty::Unknown,
@@ -900,11 +878,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
900 else_branch, 878 else_branch,
901 } => { 879 } => {
902 // if let is desugared to match, so this is always simple if 880 // if let is desugared to match, so this is always simple if
903 self.infer_expr(*condition, &Expectation::has_type(Ty::Bool))?; 881 self.infer_expr(*condition, &Expectation::has_type(Ty::Bool));
904 let then_ty = self.infer_expr(*then_branch, expected)?; 882 let then_ty = self.infer_expr(*then_branch, expected);
905 match else_branch { 883 match else_branch {
906 Some(else_branch) => { 884 Some(else_branch) => {
907 self.infer_expr(*else_branch, expected)?; 885 self.infer_expr(*else_branch, expected);
908 } 886 }
909 None => { 887 None => {
910 // no else branch -> unit 888 // no else branch -> unit
@@ -913,31 +891,31 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
913 }; 891 };
914 then_ty 892 then_ty
915 } 893 }
916 Expr::Block { statements, tail } => self.infer_block(statements, *tail, expected)?, 894 Expr::Block { statements, tail } => self.infer_block(statements, *tail, expected),
917 Expr::Loop { body } => { 895 Expr::Loop { body } => {
918 self.infer_expr(*body, &Expectation::has_type(Ty::unit()))?; 896 self.infer_expr(*body, &Expectation::has_type(Ty::unit()));
919 // TODO handle break with value 897 // TODO handle break with value
920 Ty::Never 898 Ty::Never
921 } 899 }
922 Expr::While { condition, body } => { 900 Expr::While { condition, body } => {
923 // while let is desugared to a match loop, so this is always simple while 901 // while let is desugared to a match loop, so this is always simple while
924 self.infer_expr(*condition, &Expectation::has_type(Ty::Bool))?; 902 self.infer_expr(*condition, &Expectation::has_type(Ty::Bool));
925 self.infer_expr(*body, &Expectation::has_type(Ty::unit()))?; 903 self.infer_expr(*body, &Expectation::has_type(Ty::unit()));
926 Ty::unit() 904 Ty::unit()
927 } 905 }
928 Expr::For { iterable, body, .. } => { 906 Expr::For { iterable, body, .. } => {
929 let _iterable_ty = self.infer_expr(*iterable, &Expectation::none()); 907 let _iterable_ty = self.infer_expr(*iterable, &Expectation::none());
930 // TODO write type for pat 908 // TODO write type for pat
931 self.infer_expr(*body, &Expectation::has_type(Ty::unit()))?; 909 self.infer_expr(*body, &Expectation::has_type(Ty::unit()));
932 Ty::unit() 910 Ty::unit()
933 } 911 }
934 Expr::Lambda { body, .. } => { 912 Expr::Lambda { body, .. } => {
935 // TODO write types for args, infer lambda type etc. 913 // TODO write types for args, infer lambda type etc.
936 let _body_ty = self.infer_expr(*body, &Expectation::none())?; 914 let _body_ty = self.infer_expr(*body, &Expectation::none());
937 Ty::Unknown 915 Ty::Unknown
938 } 916 }
939 Expr::Call { callee, args } => { 917 Expr::Call { callee, args } => {
940 let callee_ty = self.infer_expr(*callee, &Expectation::none())?; 918 let callee_ty = self.infer_expr(*callee, &Expectation::none());
941 let (param_tys, ret_ty) = match &callee_ty { 919 let (param_tys, ret_ty) = match &callee_ty {
942 Ty::FnPtr(sig) => (&sig.input[..], sig.output.clone()), 920 Ty::FnPtr(sig) => (&sig.input[..], sig.output.clone()),
943 _ => { 921 _ => {
@@ -950,7 +928,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
950 self.infer_expr( 928 self.infer_expr(
951 *arg, 929 *arg,
952 &Expectation::has_type(param_tys.get(i).cloned().unwrap_or(Ty::Unknown)), 930 &Expectation::has_type(param_tys.get(i).cloned().unwrap_or(Ty::Unknown)),
953 )?; 931 );
954 } 932 }
955 ret_ty 933 ret_ty
956 } 934 }
@@ -959,12 +937,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
959 args, 937 args,
960 method_name, 938 method_name,
961 } => { 939 } => {
962 let receiver_ty = self.infer_expr(*receiver, &Expectation::none())?; 940 let receiver_ty = self.infer_expr(*receiver, &Expectation::none());
963 let resolved = receiver_ty.clone().lookup_method(self.db, method_name)?; 941 let resolved = receiver_ty.clone().lookup_method(self.db, method_name);
964 let method_ty = match resolved { 942 let method_ty = match resolved {
965 Some(def_id) => { 943 Some(def_id) => {
966 self.write_method_resolution(expr, def_id); 944 self.write_method_resolution(expr, def_id);
967 self.db.type_for_def(def_id)? 945 self.db.type_for_def(def_id)
968 } 946 }
969 None => Ty::Unknown, 947 None => Ty::Unknown,
970 }; 948 };
@@ -986,32 +964,32 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
986 self.infer_expr( 964 self.infer_expr(
987 *arg, 965 *arg,
988 &Expectation::has_type(param_tys.get(i).cloned().unwrap_or(Ty::Unknown)), 966 &Expectation::has_type(param_tys.get(i).cloned().unwrap_or(Ty::Unknown)),
989 )?; 967 );
990 } 968 }
991 ret_ty 969 ret_ty
992 } 970 }
993 Expr::Match { expr, arms } => { 971 Expr::Match { expr, arms } => {
994 let _ty = self.infer_expr(*expr, &Expectation::none())?; 972 let _ty = self.infer_expr(*expr, &Expectation::none());
995 for arm in arms { 973 for arm in arms {
996 // TODO type the bindings in pats 974 // TODO type the bindings in pats
997 // TODO type the guard 975 // TODO type the guard
998 let _ty = self.infer_expr(arm.expr, &Expectation::none())?; 976 let _ty = self.infer_expr(arm.expr, &Expectation::none());
999 } 977 }
1000 // TODO unify all the match arm types 978 // TODO unify all the match arm types
1001 Ty::Unknown 979 Ty::Unknown
1002 } 980 }
1003 Expr::Path(p) => self.infer_path_expr(expr, p)?.unwrap_or(Ty::Unknown), 981 Expr::Path(p) => self.infer_path_expr(expr, p).unwrap_or(Ty::Unknown),
1004 Expr::Continue => Ty::Never, 982 Expr::Continue => Ty::Never,
1005 Expr::Break { expr } => { 983 Expr::Break { expr } => {
1006 if let Some(expr) = expr { 984 if let Some(expr) = expr {
1007 // TODO handle break with value 985 // TODO handle break with value
1008 self.infer_expr(*expr, &Expectation::none())?; 986 self.infer_expr(*expr, &Expectation::none());
1009 } 987 }
1010 Ty::Never 988 Ty::Never
1011 } 989 }
1012 Expr::Return { expr } => { 990 Expr::Return { expr } => {
1013 if let Some(expr) = expr { 991 if let Some(expr) = expr {
1014 self.infer_expr(*expr, &Expectation::has_type(self.return_ty.clone()))?; 992 self.infer_expr(*expr, &Expectation::has_type(self.return_ty.clone()));
1015 } 993 }
1016 Ty::Never 994 Ty::Never
1017 } 995 }
@@ -1020,60 +998,58 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1020 fields, 998 fields,
1021 spread, 999 spread,
1022 } => { 1000 } => {
1023 let (ty, def_id) = self.resolve_variant(path.as_ref())?; 1001 let (ty, def_id) = self.resolve_variant(path.as_ref());
1024 for field in fields { 1002 for field in fields {
1025 let field_ty = if let Some(def_id) = def_id { 1003 let field_ty = if let Some(def_id) = def_id {
1026 self.db 1004 self.db
1027 .type_for_field(def_id, field.name.clone())? 1005 .type_for_field(def_id, field.name.clone())
1028 .unwrap_or(Ty::Unknown) 1006 .unwrap_or(Ty::Unknown)
1029 } else { 1007 } else {
1030 Ty::Unknown 1008 Ty::Unknown
1031 }; 1009 };
1032 self.infer_expr(field.expr, &Expectation::has_type(field_ty))?; 1010 self.infer_expr(field.expr, &Expectation::has_type(field_ty));
1033 } 1011 }
1034 if let Some(expr) = spread { 1012 if let Some(expr) = spread {
1035 self.infer_expr(*expr, &Expectation::has_type(ty.clone()))?; 1013 self.infer_expr(*expr, &Expectation::has_type(ty.clone()));
1036 } 1014 }
1037 ty 1015 ty
1038 } 1016 }
1039 Expr::Field { expr, name } => { 1017 Expr::Field { expr, name } => {
1040 let receiver_ty = self.infer_expr(*expr, &Expectation::none())?; 1018 let receiver_ty = self.infer_expr(*expr, &Expectation::none());
1041 let ty = receiver_ty 1019 let ty = receiver_ty
1042 .autoderef(self.db) 1020 .autoderef(self.db)
1043 .find_map(|derefed_ty| match derefed_ty { 1021 .find_map(|derefed_ty| match derefed_ty {
1044 // this is more complicated than necessary because type_for_field is cancelable 1022 // this is more complicated than necessary because type_for_field is cancelable
1045 Ty::Tuple(fields) => { 1023 Ty::Tuple(fields) => {
1046 let i = name.to_string().parse::<usize>().ok(); 1024 let i = name.to_string().parse::<usize>().ok();
1047 i.and_then(|i| fields.get(i).cloned()).map(Ok) 1025 i.and_then(|i| fields.get(i).cloned())
1048 }
1049 Ty::Adt { def_id, .. } => {
1050 transpose(self.db.type_for_field(def_id, name.clone()))
1051 } 1026 }
1027 Ty::Adt { def_id, .. } => self.db.type_for_field(def_id, name.clone()),
1052 _ => None, 1028 _ => None,
1053 }) 1029 })
1054 .unwrap_or(Ok(Ty::Unknown))?; 1030 .unwrap_or(Ty::Unknown);
1055 self.insert_type_vars(ty) 1031 self.insert_type_vars(ty)
1056 } 1032 }
1057 Expr::Try { expr } => { 1033 Expr::Try { expr } => {
1058 let _inner_ty = self.infer_expr(*expr, &Expectation::none())?; 1034 let _inner_ty = self.infer_expr(*expr, &Expectation::none());
1059 Ty::Unknown 1035 Ty::Unknown
1060 } 1036 }
1061 Expr::Cast { expr, type_ref } => { 1037 Expr::Cast { expr, type_ref } => {
1062 let _inner_ty = self.infer_expr(*expr, &Expectation::none())?; 1038 let _inner_ty = self.infer_expr(*expr, &Expectation::none());
1063 let cast_ty = 1039 let cast_ty =
1064 Ty::from_hir(self.db, &self.module, self.impl_block.as_ref(), type_ref)?; 1040 Ty::from_hir(self.db, &self.module, self.impl_block.as_ref(), type_ref);
1065 let cast_ty = self.insert_type_vars(cast_ty); 1041 let cast_ty = self.insert_type_vars(cast_ty);
1066 // TODO check the cast... 1042 // TODO check the cast...
1067 cast_ty 1043 cast_ty
1068 } 1044 }
1069 Expr::Ref { expr, mutability } => { 1045 Expr::Ref { expr, mutability } => {
1070 // TODO pass the expectation down 1046 // TODO pass the expectation down
1071 let inner_ty = self.infer_expr(*expr, &Expectation::none())?; 1047 let inner_ty = self.infer_expr(*expr, &Expectation::none());
1072 // TODO reference coercions etc. 1048 // TODO reference coercions etc.
1073 Ty::Ref(Arc::new(inner_ty), *mutability) 1049 Ty::Ref(Arc::new(inner_ty), *mutability)
1074 } 1050 }
1075 Expr::UnaryOp { expr, op } => { 1051 Expr::UnaryOp { expr, op } => {
1076 let inner_ty = self.infer_expr(*expr, &Expectation::none())?; 1052 let inner_ty = self.infer_expr(*expr, &Expectation::none());
1077 match op { 1053 match op {
1078 Some(UnaryOp::Deref) => { 1054 Some(UnaryOp::Deref) => {
1079 if let Some(derefed_ty) = inner_ty.builtin_deref() { 1055 if let Some(derefed_ty) = inner_ty.builtin_deref() {
@@ -1094,11 +1070,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1094 } 1070 }
1095 _ => Expectation::none(), 1071 _ => Expectation::none(),
1096 }; 1072 };
1097 let lhs_ty = self.infer_expr(*lhs, &lhs_expectation)?; 1073 let lhs_ty = self.infer_expr(*lhs, &lhs_expectation);
1098 // TODO: find implementation of trait corresponding to operation 1074 // TODO: find implementation of trait corresponding to operation
1099 // symbol and resolve associated `Output` type 1075 // symbol and resolve associated `Output` type
1100 let rhs_expectation = binary_op_rhs_expectation(*op, lhs_ty); 1076 let rhs_expectation = binary_op_rhs_expectation(*op, lhs_ty);
1101 let rhs_ty = self.infer_expr(*rhs, &Expectation::has_type(rhs_expectation))?; 1077 let rhs_ty = self.infer_expr(*rhs, &Expectation::has_type(rhs_expectation));
1102 1078
1103 // TODO: similar as above, return ty is often associated trait type 1079 // TODO: similar as above, return ty is often associated trait type
1104 binary_op_return_ty(*op, rhs_ty) 1080 binary_op_return_ty(*op, rhs_ty)
@@ -1108,7 +1084,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1108 Expr::Tuple { exprs } => { 1084 Expr::Tuple { exprs } => {
1109 let mut ty_vec = Vec::with_capacity(exprs.len()); 1085 let mut ty_vec = Vec::with_capacity(exprs.len());
1110 for arg in exprs.iter() { 1086 for arg in exprs.iter() {
1111 ty_vec.push(self.infer_expr(*arg, &Expectation::none())?); 1087 ty_vec.push(self.infer_expr(*arg, &Expectation::none()));
1112 } 1088 }
1113 1089
1114 Ty::Tuple(Arc::from(ty_vec)) 1090 Ty::Tuple(Arc::from(ty_vec))
@@ -1133,7 +1109,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1133 self.unify(&ty, &expected.ty); 1109 self.unify(&ty, &expected.ty);
1134 let ty = self.resolve_ty_as_possible(ty); 1110 let ty = self.resolve_ty_as_possible(ty);
1135 self.write_expr_ty(expr, ty.clone()); 1111 self.write_expr_ty(expr, ty.clone());
1136 Ok(ty) 1112 ty
1137 } 1113 }
1138 1114
1139 fn infer_block( 1115 fn infer_block(
@@ -1141,7 +1117,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1141 statements: &[Statement], 1117 statements: &[Statement],
1142 tail: Option<ExprId>, 1118 tail: Option<ExprId>,
1143 expected: &Expectation, 1119 expected: &Expectation,
1144 ) -> Cancelable<Ty> { 1120 ) -> Ty {
1145 for stmt in statements { 1121 for stmt in statements {
1146 match stmt { 1122 match stmt {
1147 Statement::Let { 1123 Statement::Let {
@@ -1154,10 +1130,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1154 &self.module, 1130 &self.module,
1155 self.impl_block.as_ref(), 1131 self.impl_block.as_ref(),
1156 type_ref.as_ref(), 1132 type_ref.as_ref(),
1157 )?; 1133 );
1158 let decl_ty = self.insert_type_vars(decl_ty); 1134 let decl_ty = self.insert_type_vars(decl_ty);
1159 let ty = if let Some(expr) = initializer { 1135 let ty = if let Some(expr) = initializer {
1160 let expr_ty = self.infer_expr(*expr, &Expectation::has_type(decl_ty))?; 1136 let expr_ty = self.infer_expr(*expr, &Expectation::has_type(decl_ty));
1161 expr_ty 1137 expr_ty
1162 } else { 1138 } else {
1163 decl_ty 1139 decl_ty
@@ -1166,43 +1142,41 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1166 self.write_pat_ty(*pat, ty); 1142 self.write_pat_ty(*pat, ty);
1167 } 1143 }
1168 Statement::Expr(expr) => { 1144 Statement::Expr(expr) => {
1169 self.infer_expr(*expr, &Expectation::none())?; 1145 self.infer_expr(*expr, &Expectation::none());
1170 } 1146 }
1171 } 1147 }
1172 } 1148 }
1173 let ty = if let Some(expr) = tail { 1149 let ty = if let Some(expr) = tail {
1174 self.infer_expr(expr, expected)? 1150 self.infer_expr(expr, expected)
1175 } else { 1151 } else {
1176 Ty::unit() 1152 Ty::unit()
1177 }; 1153 };
1178 Ok(ty) 1154 ty
1179 } 1155 }
1180 1156
1181 fn collect_fn_signature(&mut self, signature: &FnSignature) -> Cancelable<()> { 1157 fn collect_fn_signature(&mut self, signature: &FnSignature) {
1182 let body = Arc::clone(&self.body); // avoid borrow checker problem 1158 let body = Arc::clone(&self.body); // avoid borrow checker problem
1183 for (type_ref, pat) in signature.params().iter().zip(body.params()) { 1159 for (type_ref, pat) in signature.params().iter().zip(body.params()) {
1184 let ty = self.make_ty(type_ref)?; 1160 let ty = self.make_ty(type_ref);
1185 let ty = self.insert_type_vars(ty); 1161 let ty = self.insert_type_vars(ty);
1186 self.write_pat_ty(*pat, ty); 1162 self.write_pat_ty(*pat, ty);
1187 } 1163 }
1188 self.return_ty = { 1164 self.return_ty = {
1189 let ty = self.make_ty(signature.ret_type())?; 1165 let ty = self.make_ty(signature.ret_type());
1190 let ty = self.insert_type_vars(ty); 1166 let ty = self.insert_type_vars(ty);
1191 ty 1167 ty
1192 }; 1168 };
1193 Ok(())
1194 } 1169 }
1195 1170
1196 fn infer_body(&mut self) -> Cancelable<()> { 1171 fn infer_body(&mut self) {
1197 self.infer_expr( 1172 self.infer_expr(
1198 self.body.body_expr(), 1173 self.body.body_expr(),
1199 &Expectation::has_type(self.return_ty.clone()), 1174 &Expectation::has_type(self.return_ty.clone()),
1200 )?; 1175 );
1201 Ok(())
1202 } 1176 }
1203} 1177}
1204 1178
1205pub fn infer(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Arc<InferenceResult>> { 1179pub fn infer(db: &impl HirDatabase, def_id: DefId) -> Arc<InferenceResult> {
1206 db.check_canceled(); 1180 db.check_canceled();
1207 let function = Function::new(def_id); // TODO: consts also need inference 1181 let function = Function::new(def_id); // TODO: consts also need inference
1208 let body = function.body(db); 1182 let body = function.body(db);
@@ -1212,9 +1186,9 @@ pub fn infer(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Arc<InferenceRe
1212 let mut ctx = InferenceContext::new(db, body, scopes, module, impl_block); 1186 let mut ctx = InferenceContext::new(db, body, scopes, module, impl_block);
1213 1187
1214 let signature = function.signature(db); 1188 let signature = function.signature(db);
1215 ctx.collect_fn_signature(&signature)?; 1189 ctx.collect_fn_signature(&signature);
1216 1190
1217 ctx.infer_body()?; 1191 ctx.infer_body();
1218 1192
1219 Ok(Arc::new(ctx.resolve_all())) 1193 Arc::new(ctx.resolve_all())
1220} 1194}
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs
index 94c5124a9..b221bd142 100644
--- a/crates/ra_hir/src/ty/method_resolution.rs
+++ b/crates/ra_hir/src/ty/method_resolution.rs
@@ -6,7 +6,7 @@ use std::sync::Arc;
6 6
7use rustc_hash::FxHashMap; 7use rustc_hash::FxHashMap;
8 8
9use ra_db::{Cancelable, SourceRootId}; 9use ra_db::SourceRootId;
10 10
11use crate::{HirDatabase, DefId, module_tree::ModuleId, Module, Crate, Name, Function, impl_block::{ImplId, ImplBlock, ImplItem}}; 11use crate::{HirDatabase, DefId, module_tree::ModuleId, Module, Crate, Name, Function, impl_block::{ImplId, ImplBlock, ImplItem}};
12use super::Ty; 12use super::Ty;
@@ -42,7 +42,7 @@ impl CrateImplBlocks {
42 &'a self, 42 &'a self,
43 db: &'a impl HirDatabase, 43 db: &'a impl HirDatabase,
44 ty: &Ty, 44 ty: &Ty,
45 ) -> impl Iterator<Item = Cancelable<ImplBlock>> + 'a { 45 ) -> impl Iterator<Item = ImplBlock> + 'a {
46 let fingerprint = TyFingerprint::for_impl(ty); 46 let fingerprint = TyFingerprint::for_impl(ty);
47 fingerprint 47 fingerprint
48 .and_then(|f| self.impls.get(&f)) 48 .and_then(|f| self.impls.get(&f))
@@ -50,11 +50,11 @@ impl CrateImplBlocks {
50 .flat_map(|i| i.iter()) 50 .flat_map(|i| i.iter())
51 .map(move |(module_id, impl_id)| { 51 .map(move |(module_id, impl_id)| {
52 let module_impl_blocks = db.impls_in_module(self.source_root_id, *module_id); 52 let module_impl_blocks = db.impls_in_module(self.source_root_id, *module_id);
53 Ok(ImplBlock::from_id(module_impl_blocks, *impl_id)) 53 ImplBlock::from_id(module_impl_blocks, *impl_id)
54 }) 54 })
55 } 55 }
56 56
57 fn collect_recursive(&mut self, db: &impl HirDatabase, module: Module) -> Cancelable<()> { 57 fn collect_recursive(&mut self, db: &impl HirDatabase, module: Module) {
58 let module_id = module.def_id.loc(db).module_id; 58 let module_id = module.def_id.loc(db).module_id;
59 let module_impl_blocks = db.impls_in_module(self.source_root_id, module_id); 59 let module_impl_blocks = db.impls_in_module(self.source_root_id, module_id);
60 60
@@ -65,7 +65,7 @@ impl CrateImplBlocks {
65 // ignore for now 65 // ignore for now
66 } else { 66 } else {
67 let target_ty = 67 let target_ty =
68 Ty::from_hir(db, &module, Some(&impl_block), impl_data.target_type())?; 68 Ty::from_hir(db, &module, Some(&impl_block), impl_data.target_type());
69 if let Some(target_ty_fp) = TyFingerprint::for_impl(&target_ty) { 69 if let Some(target_ty_fp) = TyFingerprint::for_impl(&target_ty) {
70 self.impls 70 self.impls
71 .entry(target_ty_fp) 71 .entry(target_ty_fp)
@@ -76,16 +76,14 @@ impl CrateImplBlocks {
76 } 76 }
77 77
78 for child in module.children(db) { 78 for child in module.children(db) {
79 self.collect_recursive(db, child)?; 79 self.collect_recursive(db, child);
80 } 80 }
81
82 Ok(())
83 } 81 }
84 82
85 pub(crate) fn impls_in_crate_query( 83 pub(crate) fn impls_in_crate_query(
86 db: &impl HirDatabase, 84 db: &impl HirDatabase,
87 krate: Crate, 85 krate: Crate,
88 ) -> Cancelable<Arc<CrateImplBlocks>> { 86 ) -> Arc<CrateImplBlocks> {
89 let crate_graph = db.crate_graph(); 87 let crate_graph = db.crate_graph();
90 let file_id = crate_graph.crate_root(krate.crate_id); 88 let file_id = crate_graph.crate_root(krate.crate_id);
91 let source_root_id = db.file_source_root(file_id); 89 let source_root_id = db.file_source_root(file_id);
@@ -94,9 +92,9 @@ impl CrateImplBlocks {
94 impls: FxHashMap::default(), 92 impls: FxHashMap::default(),
95 }; 93 };
96 if let Some(module) = krate.root_module(db) { 94 if let Some(module) = krate.root_module(db) {
97 crate_impl_blocks.collect_recursive(db, module)?; 95 crate_impl_blocks.collect_recursive(db, module);
98 } 96 }
99 Ok(Arc::new(crate_impl_blocks)) 97 Arc::new(crate_impl_blocks)
100 } 98 }
101} 99}
102 100
@@ -111,13 +109,13 @@ impl Ty {
111 // TODO: cache this as a query? 109 // TODO: cache this as a query?
112 // - if so, what signature? (TyFingerprint, Name)? 110 // - if so, what signature? (TyFingerprint, Name)?
113 // - or maybe cache all names and def_ids of methods per fingerprint? 111 // - or maybe cache all names and def_ids of methods per fingerprint?
114 pub fn lookup_method(self, db: &impl HirDatabase, name: &Name) -> Cancelable<Option<DefId>> { 112 pub fn lookup_method(self, db: &impl HirDatabase, name: &Name) -> Option<DefId> {
115 self.iterate_methods(db, |f| { 113 self.iterate_methods(db, |f| {
116 let sig = f.signature(db); 114 let sig = f.signature(db);
117 if sig.name() == name && sig.has_self_param() { 115 if sig.name() == name && sig.has_self_param() {
118 Ok(Some(f.def_id())) 116 Some(f.def_id())
119 } else { 117 } else {
120 Ok(None) 118 None
121 } 119 }
122 }) 120 })
123 } 121 }
@@ -127,8 +125,8 @@ impl Ty {
127 pub fn iterate_methods<T>( 125 pub fn iterate_methods<T>(
128 self, 126 self,
129 db: &impl HirDatabase, 127 db: &impl HirDatabase,
130 mut callback: impl FnMut(Function) -> Cancelable<Option<T>>, 128 mut callback: impl FnMut(Function) -> Option<T>,
131 ) -> Cancelable<Option<T>> { 129 ) -> Option<T> {
132 // For method calls, rust first does any number of autoderef, and then one 130 // For method calls, rust first does any number of autoderef, and then one
133 // autoref (i.e. when the method takes &self or &mut self). We just ignore 131 // autoref (i.e. when the method takes &self or &mut self). We just ignore
134 // the autoref currently -- when we find a method matching the given name, 132 // the autoref currently -- when we find a method matching the given name,
@@ -143,15 +141,14 @@ impl Ty {
143 Some(krate) => krate, 141 Some(krate) => krate,
144 None => continue, 142 None => continue,
145 }; 143 };
146 let impls = db.impls_in_crate(krate)?; 144 let impls = db.impls_in_crate(krate);
147 145
148 for impl_block in impls.lookup_impl_blocks(db, &derefed_ty) { 146 for impl_block in impls.lookup_impl_blocks(db, &derefed_ty) {
149 let impl_block = impl_block?;
150 for item in impl_block.items() { 147 for item in impl_block.items() {
151 match item { 148 match item {
152 ImplItem::Method(f) => { 149 ImplItem::Method(f) => {
153 if let Some(result) = callback(f.clone())? { 150 if let Some(result) = callback(f.clone()) {
154 return Ok(Some(result)); 151 return Some(result);
155 } 152 }
156 } 153 }
157 _ => {} 154 _ => {}
@@ -159,6 +156,6 @@ impl Ty {
159 } 156 }
160 } 157 }
161 } 158 }
162 Ok(None) 159 None
163 } 160 }
164} 161}
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index b44ac9987..929fee04c 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -321,7 +321,7 @@ fn infer(content: &str) -> String {
321 .filter_map(ast::FnDef::cast) 321 .filter_map(ast::FnDef::cast)
322 { 322 {
323 let func = source_binder::function_from_source(&db, file_id, fn_def).unwrap(); 323 let func = source_binder::function_from_source(&db, file_id, fn_def).unwrap();
324 let inference_result = func.infer(&db).unwrap(); 324 let inference_result = func.infer(&db);
325 let body_syntax_mapping = func.body_syntax_mapping(&db); 325 let body_syntax_mapping = func.body_syntax_mapping(&db);
326 let mut types = Vec::new(); 326 let mut types = Vec::new();
327 for (pat, ty) in inference_result.type_of_pat.iter() { 327 for (pat, ty) in inference_result.type_of_pat.iter() {
@@ -405,7 +405,7 @@ fn typing_whitespace_inside_a_function_should_not_invalidate_types() {
405 let func = source_binder::function_from_position(&db, pos).unwrap(); 405 let func = source_binder::function_from_position(&db, pos).unwrap();
406 { 406 {
407 let events = db.log_executed(|| { 407 let events = db.log_executed(|| {
408 func.infer(&db).unwrap(); 408 func.infer(&db);
409 }); 409 });
410 assert!(format!("{:?}", events).contains("infer")) 410 assert!(format!("{:?}", events).contains("infer"))
411 } 411 }
@@ -424,7 +424,7 @@ fn typing_whitespace_inside_a_function_should_not_invalidate_types() {
424 424
425 { 425 {
426 let events = db.log_executed(|| { 426 let events = db.log_executed(|| {
427 func.infer(&db).unwrap(); 427 func.infer(&db);
428 }); 428 });
429 assert!(!format!("{:?}", events).contains("infer"), "{:#?}", events) 429 assert!(!format!("{:?}", events).contains("infer"), "{:#?}", events)
430 } 430 }
diff --git a/crates/ra_ide_api/src/call_info.rs b/crates/ra_ide_api/src/call_info.rs
index efa320d83..18b9508ef 100644
--- a/crates/ra_ide_api/src/call_info.rs
+++ b/crates/ra_ide_api/src/call_info.rs
@@ -1,6 +1,6 @@
1use std::cmp::{max, min}; 1use std::cmp::{max, min};
2 2
3use ra_db::{SyntaxDatabase, Cancelable}; 3use ra_db::SyntaxDatabase;
4use ra_syntax::{ 4use ra_syntax::{
5 AstNode, SyntaxNode, TextUnit, TextRange, 5 AstNode, SyntaxNode, TextUnit, TextRange,
6 SyntaxKind::FN_DEF, 6 SyntaxKind::FN_DEF,
@@ -11,21 +11,23 @@ use ra_syntax::{
11use crate::{FilePosition, CallInfo, db::RootDatabase}; 11use crate::{FilePosition, CallInfo, db::RootDatabase};
12 12
13/// Computes parameter information for the given call expression. 13/// Computes parameter information for the given call expression.
14pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Cancelable<Option<CallInfo>> { 14pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<CallInfo> {
15 let file = db.source_file(position.file_id); 15 let file = db.source_file(position.file_id);
16 let syntax = file.syntax(); 16 let syntax = file.syntax();
17 17
18 // Find the calling expression and it's NameRef 18 // Find the calling expression and it's NameRef
19 let calling_node = ctry!(FnCallNode::with_node(syntax, position.offset)); 19 let calling_node = FnCallNode::with_node(syntax, position.offset)?;
20 let name_ref = ctry!(calling_node.name_ref()); 20 let name_ref = calling_node.name_ref()?;
21 21
22 // Resolve the function's NameRef (NOTE: this isn't entirely accurate). 22 // Resolve the function's NameRef (NOTE: this isn't entirely accurate).
23 let file_symbols = db.index_resolve(name_ref); 23 let file_symbols = db.index_resolve(name_ref);
24 let symbol = ctry!(file_symbols.into_iter().find(|it| it.ptr.kind() == FN_DEF)); 24 let symbol = file_symbols
25 .into_iter()
26 .find(|it| it.ptr.kind() == FN_DEF)?;
25 let fn_file = db.source_file(symbol.file_id); 27 let fn_file = db.source_file(symbol.file_id);
26 let fn_def = symbol.ptr.resolve(&fn_file); 28 let fn_def = symbol.ptr.resolve(&fn_file);
27 let fn_def = ast::FnDef::cast(&fn_def).unwrap(); 29 let fn_def = ast::FnDef::cast(&fn_def).unwrap();
28 let mut call_info = ctry!(CallInfo::new(fn_def)); 30 let mut call_info = CallInfo::new(fn_def)?;
29 // If we have a calling expression let's find which argument we are on 31 // If we have a calling expression let's find which argument we are on
30 let num_params = call_info.parameters.len(); 32 let num_params = call_info.parameters.len();
31 let has_self = fn_def.param_list().and_then(|l| l.self_param()).is_some(); 33 let has_self = fn_def.param_list().and_then(|l| l.self_param()).is_some();
@@ -61,7 +63,7 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Cancelable
61 } 63 }
62 } 64 }
63 65
64 Ok(Some(call_info)) 66 Some(call_info)
65} 67}
66 68
67enum FnCallNode<'a> { 69enum FnCallNode<'a> {
diff --git a/crates/ra_ide_api/src/completion.rs b/crates/ra_ide_api/src/completion.rs
index ce777a771..b03ddd74c 100644
--- a/crates/ra_ide_api/src/completion.rs
+++ b/crates/ra_ide_api/src/completion.rs
@@ -12,7 +12,7 @@ use ra_db::SyntaxDatabase;
12 12
13use crate::{ 13use crate::{
14 db, 14 db,
15 Cancelable, FilePosition, 15 FilePosition,
16 completion::{ 16 completion::{
17 completion_item::{Completions, CompletionKind}, 17 completion_item::{Completions, CompletionKind},
18 completion_context::CompletionContext, 18 completion_context::CompletionContext,
@@ -43,12 +43,9 @@ pub use crate::completion::completion_item::{CompletionItem, InsertText, Complet
43/// `foo` *should* be present among the completion variants. Filtering by 43/// `foo` *should* be present among the completion variants. Filtering by
44/// identifier prefix/fuzzy match should be done higher in the stack, together 44/// identifier prefix/fuzzy match should be done higher in the stack, together
45/// with ordering of completions (currently this is done by the client). 45/// with ordering of completions (currently this is done by the client).
46pub(crate) fn completions( 46pub(crate) fn completions(db: &db::RootDatabase, position: FilePosition) -> Option<Completions> {
47 db: &db::RootDatabase,
48 position: FilePosition,
49) -> Cancelable<Option<Completions>> {
50 let original_file = db.source_file(position.file_id); 47 let original_file = db.source_file(position.file_id);
51 let ctx = ctry!(CompletionContext::new(db, &original_file, position)?); 48 let ctx = CompletionContext::new(db, &original_file, position)?;
52 49
53 let mut acc = Completions::default(); 50 let mut acc = Completions::default();
54 51
@@ -57,11 +54,11 @@ pub(crate) fn completions(
57 complete_keyword::complete_use_tree_keyword(&mut acc, &ctx); 54 complete_keyword::complete_use_tree_keyword(&mut acc, &ctx);
58 complete_snippet::complete_expr_snippet(&mut acc, &ctx); 55 complete_snippet::complete_expr_snippet(&mut acc, &ctx);
59 complete_snippet::complete_item_snippet(&mut acc, &ctx); 56 complete_snippet::complete_item_snippet(&mut acc, &ctx);
60 complete_path::complete_path(&mut acc, &ctx)?; 57 complete_path::complete_path(&mut acc, &ctx);
61 complete_scope::complete_scope(&mut acc, &ctx)?; 58 complete_scope::complete_scope(&mut acc, &ctx);
62 complete_dot::complete_dot(&mut acc, &ctx)?; 59 complete_dot::complete_dot(&mut acc, &ctx);
63 60
64 Ok(Some(acc)) 61 Some(acc)
65} 62}
66 63
67#[cfg(test)] 64#[cfg(test)]
@@ -72,6 +69,6 @@ fn check_completion(code: &str, expected_completions: &str, kind: CompletionKind
72 } else { 69 } else {
73 single_file_with_position(code) 70 single_file_with_position(code)
74 }; 71 };
75 let completions = completions(&analysis.db, position).unwrap().unwrap(); 72 let completions = completions(&analysis.db, position).unwrap();
76 completions.assert_match(expected_completions, kind); 73 completions.assert_match(expected_completions, kind);
77} 74}
diff --git a/crates/ra_ide_api/src/completion/complete_dot.rs b/crates/ra_ide_api/src/completion/complete_dot.rs
index cb86ba9a3..473edc50e 100644
--- a/crates/ra_ide_api/src/completion/complete_dot.rs
+++ b/crates/ra_ide_api/src/completion/complete_dot.rs
@@ -1,29 +1,27 @@
1use hir::{Ty, Def}; 1use hir::{Ty, Def};
2 2
3use crate::Cancelable;
4use crate::completion::{CompletionContext, Completions, CompletionKind, CompletionItem, CompletionItemKind}; 3use crate::completion::{CompletionContext, Completions, CompletionKind, CompletionItem, CompletionItemKind};
5 4
6/// Complete dot accesses, i.e. fields or methods (currently only fields). 5/// Complete dot accesses, i.e. fields or methods (currently only fields).
7pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) -> Cancelable<()> { 6pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) {
8 let (function, receiver) = match (&ctx.function, ctx.dot_receiver) { 7 let (function, receiver) = match (&ctx.function, ctx.dot_receiver) {
9 (Some(function), Some(receiver)) => (function, receiver), 8 (Some(function), Some(receiver)) => (function, receiver),
10 _ => return Ok(()), 9 _ => return,
11 }; 10 };
12 let infer_result = function.infer(ctx.db)?; 11 let infer_result = function.infer(ctx.db);
13 let syntax_mapping = function.body_syntax_mapping(ctx.db); 12 let syntax_mapping = function.body_syntax_mapping(ctx.db);
14 let expr = match syntax_mapping.node_expr(receiver) { 13 let expr = match syntax_mapping.node_expr(receiver) {
15 Some(expr) => expr, 14 Some(expr) => expr,
16 None => return Ok(()), 15 None => return,
17 }; 16 };
18 let receiver_ty = infer_result[expr].clone(); 17 let receiver_ty = infer_result[expr].clone();
19 if !ctx.is_call { 18 if !ctx.is_call {
20 complete_fields(acc, ctx, receiver_ty.clone())?; 19 complete_fields(acc, ctx, receiver_ty.clone());
21 } 20 }
22 complete_methods(acc, ctx, receiver_ty)?; 21 complete_methods(acc, ctx, receiver_ty);
23 Ok(())
24} 22}
25 23
26fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) -> Cancelable<()> { 24fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) {
27 for receiver in receiver.autoderef(ctx.db) { 25 for receiver in receiver.autoderef(ctx.db) {
28 match receiver { 26 match receiver {
29 Ty::Adt { def_id, .. } => { 27 Ty::Adt { def_id, .. } => {
@@ -35,7 +33,7 @@ fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty)
35 field.name().to_string(), 33 field.name().to_string(),
36 ) 34 )
37 .kind(CompletionItemKind::Field) 35 .kind(CompletionItemKind::Field)
38 .set_detail(field.ty(ctx.db)?.map(|ty| ty.to_string())) 36 .set_detail(field.ty(ctx.db).map(|ty| ty.to_string()))
39 .add_to(acc); 37 .add_to(acc);
40 } 38 }
41 } 39 }
@@ -53,14 +51,9 @@ fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty)
53 _ => {} 51 _ => {}
54 }; 52 };
55 } 53 }
56 Ok(())
57} 54}
58 55
59fn complete_methods( 56fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) {
60 acc: &mut Completions,
61 ctx: &CompletionContext,
62 receiver: Ty,
63) -> Cancelable<()> {
64 receiver.iterate_methods(ctx.db, |func| { 57 receiver.iterate_methods(ctx.db, |func| {
65 let sig = func.signature(ctx.db); 58 let sig = func.signature(ctx.db);
66 if sig.has_self_param() { 59 if sig.has_self_param() {
@@ -69,9 +62,8 @@ fn complete_methods(
69 .kind(CompletionItemKind::Method) 62 .kind(CompletionItemKind::Method)
70 .add_to(acc); 63 .add_to(acc);
71 } 64 }
72 Ok(None::<()>) 65 None::<()>
73 })?; 66 });
74 Ok(())
75} 67}
76 68
77#[cfg(test)] 69#[cfg(test)]
diff --git a/crates/ra_ide_api/src/completion/complete_path.rs b/crates/ra_ide_api/src/completion/complete_path.rs
index 42468681a..1eded7658 100644
--- a/crates/ra_ide_api/src/completion/complete_path.rs
+++ b/crates/ra_ide_api/src/completion/complete_path.rs
@@ -1,16 +1,15 @@
1use crate::{ 1use crate::{
2 Cancelable,
3 completion::{CompletionItem, CompletionItemKind, Completions, CompletionKind, CompletionContext}, 2 completion::{CompletionItem, CompletionItemKind, Completions, CompletionKind, CompletionContext},
4}; 3};
5 4
6pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) -> Cancelable<()> { 5pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
7 let (path, module) = match (&ctx.path_prefix, &ctx.module) { 6 let (path, module) = match (&ctx.path_prefix, &ctx.module) {
8 (Some(path), Some(module)) => (path.clone(), module), 7 (Some(path), Some(module)) => (path.clone(), module),
9 _ => return Ok(()), 8 _ => return,
10 }; 9 };
11 let def_id = match module.resolve_path(ctx.db, &path).take_types() { 10 let def_id = match module.resolve_path(ctx.db, &path).take_types() {
12 Some(it) => it, 11 Some(it) => it,
13 None => return Ok(()), 12 None => return,
14 }; 13 };
15 match def_id.resolve(ctx.db) { 14 match def_id.resolve(ctx.db) {
16 hir::Def::Module(module) => { 15 hir::Def::Module(module) => {
@@ -30,9 +29,8 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) -> C
30 .add_to(acc) 29 .add_to(acc)
31 }); 30 });
32 } 31 }
33 _ => return Ok(()), 32 _ => return,
34 }; 33 };
35 Ok(())
36} 34}
37 35
38#[cfg(test)] 36#[cfg(test)]
diff --git a/crates/ra_ide_api/src/completion/complete_scope.rs b/crates/ra_ide_api/src/completion/complete_scope.rs
index 660c7d16e..699680748 100644
--- a/crates/ra_ide_api/src/completion/complete_scope.rs
+++ b/crates/ra_ide_api/src/completion/complete_scope.rs
@@ -1,18 +1,15 @@
1use rustc_hash::FxHashSet; 1use rustc_hash::FxHashSet;
2use ra_syntax::TextUnit; 2use ra_syntax::TextUnit;
3 3
4use crate::{ 4use crate::completion::{CompletionItem, CompletionItemKind, Completions, CompletionKind, CompletionContext};
5 Cancelable,
6 completion::{CompletionItem, CompletionItemKind, Completions, CompletionKind, CompletionContext},
7};
8 5
9pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) -> Cancelable<()> { 6pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) {
10 if !ctx.is_trivial_path { 7 if !ctx.is_trivial_path {
11 return Ok(()); 8 return;
12 } 9 }
13 let module = match &ctx.module { 10 let module = match &ctx.module {
14 Some(it) => it, 11 Some(it) => it,
15 None => return Ok(()), 12 None => return,
16 }; 13 };
17 if let Some(function) = &ctx.function { 14 if let Some(function) = &ctx.function {
18 let scopes = function.scopes(ctx.db); 15 let scopes = function.scopes(ctx.db);
@@ -40,7 +37,6 @@ pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) ->
40 .from_resolution(ctx, res) 37 .from_resolution(ctx, res)
41 .add_to(acc) 38 .add_to(acc)
42 }); 39 });
43 Ok(())
44} 40}
45 41
46fn complete_fn(acc: &mut Completions, scopes: &hir::ScopesWithSyntaxMapping, offset: TextUnit) { 42fn complete_fn(acc: &mut Completions, scopes: &hir::ScopesWithSyntaxMapping, offset: TextUnit) {
diff --git a/crates/ra_ide_api/src/completion/completion_context.rs b/crates/ra_ide_api/src/completion/completion_context.rs
index f5b5ed689..e537e0082 100644
--- a/crates/ra_ide_api/src/completion/completion_context.rs
+++ b/crates/ra_ide_api/src/completion/completion_context.rs
@@ -7,7 +7,7 @@ use ra_syntax::{
7}; 7};
8use hir::source_binder; 8use hir::source_binder;
9 9
10use crate::{db, FilePosition, Cancelable}; 10use crate::{db, FilePosition};
11 11
12/// `CompletionContext` is created early during completion to figure out, where 12/// `CompletionContext` is created early during completion to figure out, where
13/// exactly is the cursor, syntax-wise. 13/// exactly is the cursor, syntax-wise.
@@ -41,10 +41,9 @@ impl<'a> CompletionContext<'a> {
41 db: &'a db::RootDatabase, 41 db: &'a db::RootDatabase,
42 original_file: &'a SourceFile, 42 original_file: &'a SourceFile,
43 position: FilePosition, 43 position: FilePosition,
44 ) -> Cancelable<Option<CompletionContext<'a>>> { 44 ) -> Option<CompletionContext<'a>> {
45 let module = source_binder::module_from_position(db, position); 45 let module = source_binder::module_from_position(db, position);
46 let leaf = 46 let leaf = find_leaf_at_offset(original_file.syntax(), position.offset).left_biased()?;
47 ctry!(find_leaf_at_offset(original_file.syntax(), position.offset).left_biased());
48 let mut ctx = CompletionContext { 47 let mut ctx = CompletionContext {
49 db, 48 db,
50 leaf, 49 leaf,
@@ -63,7 +62,7 @@ impl<'a> CompletionContext<'a> {
63 is_call: false, 62 is_call: false,
64 }; 63 };
65 ctx.fill(original_file, position.offset); 64 ctx.fill(original_file, position.offset);
66 Ok(Some(ctx)) 65 Some(ctx)
67 } 66 }
68 67
69 fn fill(&mut self, original_file: &'a SourceFile, offset: TextUnit) { 68 fn fill(&mut self, original_file: &'a SourceFile, offset: TextUnit) {
diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs
index cdd8e211d..b1becca03 100644
--- a/crates/ra_ide_api/src/goto_definition.rs
+++ b/crates/ra_ide_api/src/goto_definition.rs
@@ -1,4 +1,4 @@
1use ra_db::{FileId, Cancelable, SyntaxDatabase}; 1use ra_db::{FileId, SyntaxDatabase};
2use ra_syntax::{ 2use ra_syntax::{
3 AstNode, ast, 3 AstNode, ast,
4 algo::find_node_at_offset, 4 algo::find_node_at_offset,
@@ -9,21 +9,18 @@ use crate::{FilePosition, NavigationTarget, db::RootDatabase, RangeInfo};
9pub(crate) fn goto_definition( 9pub(crate) fn goto_definition(
10 db: &RootDatabase, 10 db: &RootDatabase,
11 position: FilePosition, 11 position: FilePosition,
12) -> Cancelable<Option<RangeInfo<Vec<NavigationTarget>>>> { 12) -> Option<RangeInfo<Vec<NavigationTarget>>> {
13 let file = db.source_file(position.file_id); 13 let file = db.source_file(position.file_id);
14 let syntax = file.syntax(); 14 let syntax = file.syntax();
15 if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, position.offset) { 15 if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, position.offset) {
16 let navs = reference_definition(db, position.file_id, name_ref)?.to_vec(); 16 let navs = reference_definition(db, position.file_id, name_ref).to_vec();
17 return Ok(Some(RangeInfo::new( 17 return Some(RangeInfo::new(name_ref.syntax().range(), navs.to_vec()));
18 name_ref.syntax().range(),
19 navs.to_vec(),
20 )));
21 } 18 }
22 if let Some(name) = find_node_at_offset::<ast::Name>(syntax, position.offset) { 19 if let Some(name) = find_node_at_offset::<ast::Name>(syntax, position.offset) {
23 let navs = ctry!(name_definition(db, position.file_id, name)?); 20 let navs = name_definition(db, position.file_id, name)?;
24 return Ok(Some(RangeInfo::new(name.syntax().range(), navs))); 21 return Some(RangeInfo::new(name.syntax().range(), navs));
25 } 22 }
26 Ok(None) 23 None
27} 24}
28 25
29pub(crate) enum ReferenceResult { 26pub(crate) enum ReferenceResult {
@@ -45,7 +42,7 @@ pub(crate) fn reference_definition(
45 db: &RootDatabase, 42 db: &RootDatabase,
46 file_id: FileId, 43 file_id: FileId,
47 name_ref: &ast::NameRef, 44 name_ref: &ast::NameRef,
48) -> Cancelable<ReferenceResult> { 45) -> ReferenceResult {
49 use self::ReferenceResult::*; 46 use self::ReferenceResult::*;
50 if let Some(function) = 47 if let Some(function) =
51 hir::source_binder::function_from_child_node(db, file_id, name_ref.syntax()) 48 hir::source_binder::function_from_child_node(db, file_id, name_ref.syntax())
@@ -54,7 +51,7 @@ pub(crate) fn reference_definition(
54 // First try to resolve the symbol locally 51 // First try to resolve the symbol locally
55 if let Some(entry) = scope.resolve_local_name(name_ref) { 52 if let Some(entry) = scope.resolve_local_name(name_ref) {
56 let nav = NavigationTarget::from_scope_entry(file_id, &entry); 53 let nav = NavigationTarget::from_scope_entry(file_id, &entry);
57 return Ok(Exact(nav)); 54 return Exact(nav);
58 }; 55 };
59 56
60 // Next check if it is a method 57 // Next check if it is a method
@@ -63,7 +60,7 @@ pub(crate) fn reference_definition(
63 .parent() 60 .parent()
64 .and_then(ast::MethodCallExpr::cast) 61 .and_then(ast::MethodCallExpr::cast)
65 { 62 {
66 let infer_result = function.infer(db)?; 63 let infer_result = function.infer(db);
67 let syntax_mapping = function.body_syntax_mapping(db); 64 let syntax_mapping = function.body_syntax_mapping(db);
68 let expr = ast::Expr::cast(method_call.syntax()).unwrap(); 65 let expr = ast::Expr::cast(method_call.syntax()).unwrap();
69 if let Some(def_id) = syntax_mapping 66 if let Some(def_id) = syntax_mapping
@@ -71,7 +68,7 @@ pub(crate) fn reference_definition(
71 .and_then(|it| infer_result.method_resolution(it)) 68 .and_then(|it| infer_result.method_resolution(it))
72 { 69 {
73 if let Some(target) = NavigationTarget::from_def(db, def_id.resolve(db)) { 70 if let Some(target) = NavigationTarget::from_def(db, def_id.resolve(db)) {
74 return Ok(Exact(target)); 71 return Exact(target);
75 } 72 }
76 }; 73 };
77 } 74 }
@@ -88,7 +85,7 @@ pub(crate) fn reference_definition(
88 let resolved = module.resolve_path(db, &path); 85 let resolved = module.resolve_path(db, &path);
89 if let Some(def_id) = resolved.take_types().or(resolved.take_values()) { 86 if let Some(def_id) = resolved.take_types().or(resolved.take_values()) {
90 if let Some(target) = NavigationTarget::from_def(db, def_id.resolve(db)) { 87 if let Some(target) = NavigationTarget::from_def(db, def_id.resolve(db)) {
91 return Ok(Exact(target)); 88 return Exact(target);
92 } 89 }
93 } 90 }
94 } 91 }
@@ -99,25 +96,25 @@ pub(crate) fn reference_definition(
99 .into_iter() 96 .into_iter()
100 .map(NavigationTarget::from_symbol) 97 .map(NavigationTarget::from_symbol)
101 .collect(); 98 .collect();
102 Ok(Approximate(navs)) 99 Approximate(navs)
103} 100}
104 101
105fn name_definition( 102fn name_definition(
106 db: &RootDatabase, 103 db: &RootDatabase,
107 file_id: FileId, 104 file_id: FileId,
108 name: &ast::Name, 105 name: &ast::Name,
109) -> Cancelable<Option<Vec<NavigationTarget>>> { 106) -> Option<Vec<NavigationTarget>> {
110 if let Some(module) = name.syntax().parent().and_then(ast::Module::cast) { 107 if let Some(module) = name.syntax().parent().and_then(ast::Module::cast) {
111 if module.has_semi() { 108 if module.has_semi() {
112 if let Some(child_module) = 109 if let Some(child_module) =
113 hir::source_binder::module_from_declaration(db, file_id, module) 110 hir::source_binder::module_from_declaration(db, file_id, module)
114 { 111 {
115 let nav = NavigationTarget::from_module(db, child_module); 112 let nav = NavigationTarget::from_module(db, child_module);
116 return Ok(Some(vec![nav])); 113 return Some(vec![nav]);
117 } 114 }
118 } 115 }
119 } 116 }
120 Ok(None) 117 None
121} 118}
122 119
123#[cfg(test)] 120#[cfg(test)]
diff --git a/crates/ra_ide_api/src/hover.rs b/crates/ra_ide_api/src/hover.rs
index 0e9c48421..d91151c15 100644
--- a/crates/ra_ide_api/src/hover.rs
+++ b/crates/ra_ide_api/src/hover.rs
@@ -1,4 +1,4 @@
1use ra_db::{Cancelable, SyntaxDatabase}; 1use ra_db::{SyntaxDatabase};
2use ra_syntax::{ 2use ra_syntax::{
3 AstNode, SyntaxNode, TreeArc, 3 AstNode, SyntaxNode, TreeArc,
4 ast::self, 4 ast::self,
@@ -7,19 +7,16 @@ use ra_syntax::{
7 7
8use crate::{db::RootDatabase, RangeInfo, FilePosition, FileRange, NavigationTarget}; 8use crate::{db::RootDatabase, RangeInfo, FilePosition, FileRange, NavigationTarget};
9 9
10pub(crate) fn hover( 10pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeInfo<String>> {
11 db: &RootDatabase,
12 position: FilePosition,
13) -> Cancelable<Option<RangeInfo<String>>> {
14 let file = db.source_file(position.file_id); 11 let file = db.source_file(position.file_id);
15 let mut res = Vec::new(); 12 let mut res = Vec::new();
16 13
17 let mut range = None; 14 let mut range = None;
18 if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(file.syntax(), position.offset) { 15 if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(file.syntax(), position.offset) {
19 use crate::goto_definition::{ReferenceResult::*, reference_definition}; 16 use crate::goto_definition::{ReferenceResult::*, reference_definition};
20 let ref_result = reference_definition(db, position.file_id, name_ref)?; 17 let ref_result = reference_definition(db, position.file_id, name_ref);
21 match ref_result { 18 match ref_result {
22 Exact(nav) => res.extend(doc_text_for(db, nav)?), 19 Exact(nav) => res.extend(doc_text_for(db, nav)),
23 Approximate(navs) => { 20 Approximate(navs) => {
24 let mut msg = String::from("Failed to exactly resolve the symbol. This is probably because rust_analyzer does not yet support glob imports or traits."); 21 let mut msg = String::from("Failed to exactly resolve the symbol. This is probably because rust_analyzer does not yet support glob imports or traits.");
25 if !navs.is_empty() { 22 if !navs.is_empty() {
@@ -27,7 +24,7 @@ pub(crate) fn hover(
27 } 24 }
28 res.push(msg); 25 res.push(msg);
29 for nav in navs { 26 for nav in navs {
30 res.extend(doc_text_for(db, nav)?) 27 res.extend(doc_text_for(db, nav))
31 } 28 }
32 } 29 }
33 } 30 }
@@ -39,25 +36,24 @@ pub(crate) fn hover(
39 let node = find_leaf_at_offset(file.syntax(), position.offset).find_map(|leaf| { 36 let node = find_leaf_at_offset(file.syntax(), position.offset).find_map(|leaf| {
40 leaf.ancestors() 37 leaf.ancestors()
41 .find(|n| ast::Expr::cast(*n).is_some() || ast::Pat::cast(*n).is_some()) 38 .find(|n| ast::Expr::cast(*n).is_some() || ast::Pat::cast(*n).is_some())
42 }); 39 })?;
43 let node = ctry!(node);
44 let frange = FileRange { 40 let frange = FileRange {
45 file_id: position.file_id, 41 file_id: position.file_id,
46 range: node.range(), 42 range: node.range(),
47 }; 43 };
48 res.extend(type_of(db, frange)?.map(Into::into)); 44 res.extend(type_of(db, frange).map(Into::into));
49 range = Some(node.range()); 45 range = Some(node.range());
50 }; 46 };
51 47
52 let range = ctry!(range); 48 let range = range?;
53 if res.is_empty() { 49 if res.is_empty() {
54 return Ok(None); 50 return None;
55 } 51 }
56 let res = RangeInfo::new(range, res.join("\n\n---\n")); 52 let res = RangeInfo::new(range, res.join("\n\n---\n"));
57 Ok(Some(res)) 53 Some(res)
58} 54}
59 55
60pub(crate) fn type_of(db: &RootDatabase, frange: FileRange) -> Cancelable<Option<String>> { 56pub(crate) fn type_of(db: &RootDatabase, frange: FileRange) -> Option<String> {
61 let file = db.source_file(frange.file_id); 57 let file = db.source_file(frange.file_id);
62 let syntax = file.syntax(); 58 let syntax = file.syntax();
63 let leaf_node = find_covering_node(syntax, frange.range); 59 let leaf_node = find_covering_node(syntax, frange.range);
@@ -67,34 +63,28 @@ pub(crate) fn type_of(db: &RootDatabase, frange: FileRange) -> Cancelable<Option
67 .take_while(|it| it.range() == leaf_node.range()) 63 .take_while(|it| it.range() == leaf_node.range())
68 .find(|&it| ast::Expr::cast(it).is_some() || ast::Pat::cast(it).is_some()) 64 .find(|&it| ast::Expr::cast(it).is_some() || ast::Pat::cast(it).is_some())
69 .unwrap_or(leaf_node); 65 .unwrap_or(leaf_node);
70 let parent_fn = ctry!(node.ancestors().find_map(ast::FnDef::cast)); 66 let parent_fn = node.ancestors().find_map(ast::FnDef::cast)?;
71 let function = ctry!(hir::source_binder::function_from_source( 67 let function = hir::source_binder::function_from_source(db, frange.file_id, parent_fn)?;
72 db, 68 let infer = function.infer(db);
73 frange.file_id,
74 parent_fn
75 ));
76 let infer = function.infer(db)?;
77 let syntax_mapping = function.body_syntax_mapping(db); 69 let syntax_mapping = function.body_syntax_mapping(db);
78 if let Some(expr) = ast::Expr::cast(node).and_then(|e| syntax_mapping.node_expr(e)) { 70 if let Some(expr) = ast::Expr::cast(node).and_then(|e| syntax_mapping.node_expr(e)) {
79 Ok(Some(infer[expr].to_string())) 71 Some(infer[expr].to_string())
80 } else if let Some(pat) = ast::Pat::cast(node).and_then(|p| syntax_mapping.node_pat(p)) { 72 } else if let Some(pat) = ast::Pat::cast(node).and_then(|p| syntax_mapping.node_pat(p)) {
81 Ok(Some(infer[pat].to_string())) 73 Some(infer[pat].to_string())
82 } else { 74 } else {
83 Ok(None) 75 None
84 } 76 }
85} 77}
86 78
87// FIXME: this should not really use navigation target. Rather, approximatelly 79// FIXME: this should not really use navigation target. Rather, approximatelly
88// resovled symbol should return a `DefId`. 80// resovled symbol should return a `DefId`.
89fn doc_text_for(db: &RootDatabase, nav: NavigationTarget) -> Cancelable<Option<String>> { 81fn doc_text_for(db: &RootDatabase, nav: NavigationTarget) -> Option<String> {
90 let result = match (nav.description(db), nav.docs(db)) { 82 match (nav.description(db), nav.docs(db)) {
91 (Some(desc), Some(docs)) => Some("```rust\n".to_string() + &*desc + "\n```\n\n" + &*docs), 83 (Some(desc), Some(docs)) => Some("```rust\n".to_string() + &*desc + "\n```\n\n" + &*docs),
92 (Some(desc), None) => Some("```rust\n".to_string() + &*desc + "\n```"), 84 (Some(desc), None) => Some("```rust\n".to_string() + &*desc + "\n```"),
93 (None, Some(docs)) => Some(docs), 85 (None, Some(docs)) => Some(docs),
94 _ => None, 86 _ => None,
95 }; 87 }
96
97 Ok(result)
98} 88}
99 89
100impl NavigationTarget { 90impl NavigationTarget {
diff --git a/crates/ra_ide_api/src/imp.rs b/crates/ra_ide_api/src/imp.rs
index 8b2cd6e27..a21cae624 100644
--- a/crates/ra_ide_api/src/imp.rs
+++ b/crates/ra_ide_api/src/imp.rs
@@ -110,14 +110,11 @@ impl db::RootDatabase {
110 }; 110 };
111 vec![krate.crate_id()] 111 vec![krate.crate_id()]
112 } 112 }
113 pub(crate) fn find_all_refs( 113 pub(crate) fn find_all_refs(&self, position: FilePosition) -> Vec<(FileId, TextRange)> {
114 &self,
115 position: FilePosition,
116 ) -> Cancelable<Vec<(FileId, TextRange)>> {
117 let file = self.source_file(position.file_id); 114 let file = self.source_file(position.file_id);
118 // Find the binding associated with the offset 115 // Find the binding associated with the offset
119 let (binding, descr) = match find_binding(self, &file, position)? { 116 let (binding, descr) = match find_binding(self, &file, position) {
120 None => return Ok(Vec::new()), 117 None => return Vec::new(),
121 Some(it) => it, 118 Some(it) => it,
122 }; 119 };
123 120
@@ -134,36 +131,30 @@ impl db::RootDatabase {
134 .map(|ref_desc| (position.file_id, ref_desc.range)), 131 .map(|ref_desc| (position.file_id, ref_desc.range)),
135 ); 132 );
136 133
137 return Ok(ret); 134 return ret;
138 135
139 fn find_binding<'a>( 136 fn find_binding<'a>(
140 db: &db::RootDatabase, 137 db: &db::RootDatabase,
141 source_file: &'a SourceFile, 138 source_file: &'a SourceFile,
142 position: FilePosition, 139 position: FilePosition,
143 ) -> Cancelable<Option<(&'a ast::BindPat, hir::Function)>> { 140 ) -> Option<(&'a ast::BindPat, hir::Function)> {
144 let syntax = source_file.syntax(); 141 let syntax = source_file.syntax();
145 if let Some(binding) = find_node_at_offset::<ast::BindPat>(syntax, position.offset) { 142 if let Some(binding) = find_node_at_offset::<ast::BindPat>(syntax, position.offset) {
146 let descr = ctry!(source_binder::function_from_child_node( 143 let descr = source_binder::function_from_child_node(
147 db, 144 db,
148 position.file_id, 145 position.file_id,
149 binding.syntax(), 146 binding.syntax(),
150 )); 147 )?;
151 return Ok(Some((binding, descr))); 148 return Some((binding, descr));
152 }; 149 };
153 let name_ref = ctry!(find_node_at_offset::<ast::NameRef>(syntax, position.offset)); 150 let name_ref = find_node_at_offset::<ast::NameRef>(syntax, position.offset)?;
154 let descr = ctry!(source_binder::function_from_child_node( 151 let descr =
155 db, 152 source_binder::function_from_child_node(db, position.file_id, name_ref.syntax())?;
156 position.file_id,
157 name_ref.syntax(),
158 ));
159 let scope = descr.scopes(db); 153 let scope = descr.scopes(db);
160 let resolved = ctry!(scope.resolve_local_name(name_ref)); 154 let resolved = scope.resolve_local_name(name_ref)?;
161 let resolved = resolved.ptr().resolve(source_file); 155 let resolved = resolved.ptr().resolve(source_file);
162 let binding = ctry!(find_node_at_offset::<ast::BindPat>( 156 let binding = find_node_at_offset::<ast::BindPat>(syntax, resolved.range().end())?;
163 syntax, 157 Some((binding, descr))
164 resolved.range().end()
165 ));
166 Ok(Some((binding, descr)))
167 } 158 }
168 } 159 }
169 160
@@ -180,7 +171,7 @@ impl db::RootDatabase {
180 }) 171 })
181 .collect::<Vec<_>>(); 172 .collect::<Vec<_>>();
182 if let Some(m) = source_binder::module_from_file_id(self, file_id) { 173 if let Some(m) = source_binder::module_from_file_id(self, file_id) {
183 for (name_node, problem) in m.problems(self)? { 174 for (name_node, problem) in m.problems(self) {
184 let source_root = self.file_source_root(file_id); 175 let source_root = self.file_source_root(file_id);
185 let diag = match problem { 176 let diag = match problem {
186 Problem::UnresolvedModule { candidate } => { 177 Problem::UnresolvedModule { candidate } => {
@@ -239,13 +230,8 @@ impl db::RootDatabase {
239 .collect() 230 .collect()
240 } 231 }
241 232
242 pub(crate) fn rename( 233 pub(crate) fn rename(&self, position: FilePosition, new_name: &str) -> Vec<SourceFileEdit> {
243 &self, 234 self.find_all_refs(position)
244 position: FilePosition,
245 new_name: &str,
246 ) -> Cancelable<Vec<SourceFileEdit>> {
247 let res = self
248 .find_all_refs(position)?
249 .iter() 235 .iter()
250 .map(|(file_id, text_range)| SourceFileEdit { 236 .map(|(file_id, text_range)| SourceFileEdit {
251 file_id: *file_id, 237 file_id: *file_id,
@@ -255,8 +241,7 @@ impl db::RootDatabase {
255 builder.finish() 241 builder.finish()
256 }, 242 },
257 }) 243 })
258 .collect::<Vec<_>>(); 244 .collect::<Vec<_>>()
259 Ok(res)
260 } 245 }
261 pub(crate) fn index_resolve(&self, name_ref: &ast::NameRef) -> Vec<FileSymbol> { 246 pub(crate) fn index_resolve(&self, name_ref: &ast::NameRef) -> Vec<FileSymbol> {
262 let name = name_ref.text(); 247 let name = name_ref.text();
diff --git a/crates/ra_ide_api/src/lib.rs b/crates/ra_ide_api/src/lib.rs
index 0f690fc84..ea5267ad9 100644
--- a/crates/ra_ide_api/src/lib.rs
+++ b/crates/ra_ide_api/src/lib.rs
@@ -9,15 +9,6 @@
9//! 9//!
10//! The sibling `ra_ide_api_light` handles thouse bits of IDE functionality 10//! The sibling `ra_ide_api_light` handles thouse bits of IDE functionality
11//! which are restricted to a single file and need only syntax. 11//! which are restricted to a single file and need only syntax.
12macro_rules! ctry {
13 ($expr:expr) => {
14 match $expr {
15 None => return Ok(None),
16 Some(it) => it,
17 }
18 };
19}
20
21mod db; 12mod db;
22mod imp; 13mod imp;
23pub mod mock_analysis; 14pub mod mock_analysis;
@@ -58,9 +49,11 @@ pub use ra_ide_api_light::{
58 LineIndex, LineCol, translate_offset_with_edit, 49 LineIndex, LineCol, translate_offset_with_edit,
59}; 50};
60pub use ra_db::{ 51pub use ra_db::{
61 Cancelable, Canceled, CrateGraph, CrateId, FileId, FilePosition, FileRange, SourceRootId 52 Canceled, CrateGraph, CrateId, FileId, FilePosition, FileRange, SourceRootId
62}; 53};
63 54
55pub type Cancelable<T> = Result<T, Canceled>;
56
64#[derive(Default)] 57#[derive(Default)]
65pub struct AnalysisChange { 58pub struct AnalysisChange {
66 new_roots: Vec<(SourceRootId, bool)>, 59 new_roots: Vec<(SourceRootId, bool)>,
@@ -393,28 +386,28 @@ impl Analysis {
393 position: FilePosition, 386 position: FilePosition,
394 ) -> Cancelable<Option<RangeInfo<Vec<NavigationTarget>>>> { 387 ) -> Cancelable<Option<RangeInfo<Vec<NavigationTarget>>>> {
395 self.db 388 self.db
396 .catch_canceled(|db| goto_definition::goto_definition(db, position))? 389 .catch_canceled(|db| goto_definition::goto_definition(db, position))
397 } 390 }
398 391
399 /// Finds all usages of the reference at point. 392 /// Finds all usages of the reference at point.
400 pub fn find_all_refs(&self, position: FilePosition) -> Cancelable<Vec<(FileId, TextRange)>> { 393 pub fn find_all_refs(&self, position: FilePosition) -> Cancelable<Vec<(FileId, TextRange)>> {
401 self.with_db(|db| db.find_all_refs(position))? 394 self.with_db(|db| db.find_all_refs(position))
402 } 395 }
403 396
404 /// Returns a short text descrbing element at position. 397 /// Returns a short text descrbing element at position.
405 pub fn hover(&self, position: FilePosition) -> Cancelable<Option<RangeInfo<String>>> { 398 pub fn hover(&self, position: FilePosition) -> Cancelable<Option<RangeInfo<String>>> {
406 self.with_db(|db| hover::hover(db, position))? 399 self.with_db(|db| hover::hover(db, position))
407 } 400 }
408 401
409 /// Computes parameter information for the given call expression. 402 /// Computes parameter information for the given call expression.
410 pub fn call_info(&self, position: FilePosition) -> Cancelable<Option<CallInfo>> { 403 pub fn call_info(&self, position: FilePosition) -> Cancelable<Option<CallInfo>> {
411 self.db 404 self.db
412 .catch_canceled(|db| call_info::call_info(db, position))? 405 .catch_canceled(|db| call_info::call_info(db, position))
413 } 406 }
414 407
415 /// Returns a `mod name;` declaration which created the current module. 408 /// Returns a `mod name;` declaration which created the current module.
416 pub fn parent_module(&self, position: FilePosition) -> Cancelable<Vec<NavigationTarget>> { 409 pub fn parent_module(&self, position: FilePosition) -> Cancelable<Vec<NavigationTarget>> {
417 self.with_db(|db| parent_module::parent_module(db, position))? 410 self.with_db(|db| parent_module::parent_module(db, position))
418 } 411 }
419 412
420 /// Returns crates this file belongs too. 413 /// Returns crates this file belongs too.
@@ -430,7 +423,7 @@ impl Analysis {
430 /// Returns the set of possible targets to run for the current file. 423 /// Returns the set of possible targets to run for the current file.
431 pub fn runnables(&self, file_id: FileId) -> Cancelable<Vec<Runnable>> { 424 pub fn runnables(&self, file_id: FileId) -> Cancelable<Vec<Runnable>> {
432 self.db 425 self.db
433 .catch_canceled(|db| runnables::runnables(db, file_id))? 426 .catch_canceled(|db| runnables::runnables(db, file_id))
434 } 427 }
435 428
436 /// Computes syntax highlighting for the given file. 429 /// Computes syntax highlighting for the given file.
@@ -443,7 +436,7 @@ impl Analysis {
443 pub fn completions(&self, position: FilePosition) -> Cancelable<Option<Vec<CompletionItem>>> { 436 pub fn completions(&self, position: FilePosition) -> Cancelable<Option<Vec<CompletionItem>>> {
444 let completions = self 437 let completions = self
445 .db 438 .db
446 .catch_canceled(|db| completion::completions(db, position))??; 439 .catch_canceled(|db| completion::completions(db, position))?;
447 Ok(completions.map(|it| it.into())) 440 Ok(completions.map(|it| it.into()))
448 } 441 }
449 442
@@ -460,7 +453,7 @@ impl Analysis {
460 453
461 /// Computes the type of the expression at the given position. 454 /// Computes the type of the expression at the given position.
462 pub fn type_of(&self, frange: FileRange) -> Cancelable<Option<String>> { 455 pub fn type_of(&self, frange: FileRange) -> Cancelable<Option<String>> {
463 self.with_db(|db| hover::type_of(db, frange))? 456 self.with_db(|db| hover::type_of(db, frange))
464 } 457 }
465 458
466 /// Returns the edit required to rename reference at the position to the new 459 /// Returns the edit required to rename reference at the position to the new
@@ -470,7 +463,7 @@ impl Analysis {
470 position: FilePosition, 463 position: FilePosition,
471 new_name: &str, 464 new_name: &str,
472 ) -> Cancelable<Vec<SourceFileEdit>> { 465 ) -> Cancelable<Vec<SourceFileEdit>> {
473 self.with_db(|db| db.rename(position, new_name))? 466 self.with_db(|db| db.rename(position, new_name))
474 } 467 }
475 468
476 fn with_db<F: FnOnce(&db::RootDatabase) -> T + std::panic::UnwindSafe, T>( 469 fn with_db<F: FnOnce(&db::RootDatabase) -> T + std::panic::UnwindSafe, T>(
diff --git a/crates/ra_ide_api/src/parent_module.rs b/crates/ra_ide_api/src/parent_module.rs
index 379b3f3a4..e94297fe3 100644
--- a/crates/ra_ide_api/src/parent_module.rs
+++ b/crates/ra_ide_api/src/parent_module.rs
@@ -1,19 +1,16 @@
1use ra_db::{Cancelable, FilePosition}; 1use ra_db::FilePosition;
2 2
3use crate::{NavigationTarget, db::RootDatabase}; 3use crate::{NavigationTarget, db::RootDatabase};
4 4
5/// This returns `Vec` because a module may be included from several places. We 5/// This returns `Vec` because a module may be included from several places. We
6/// don't handle this case yet though, so the Vec has length at most one. 6/// don't handle this case yet though, so the Vec has length at most one.
7pub(crate) fn parent_module( 7pub(crate) fn parent_module(db: &RootDatabase, position: FilePosition) -> Vec<NavigationTarget> {
8 db: &RootDatabase,
9 position: FilePosition,
10) -> Cancelable<Vec<NavigationTarget>> {
11 let module = match hir::source_binder::module_from_position(db, position) { 8 let module = match hir::source_binder::module_from_position(db, position) {
12 None => return Ok(Vec::new()), 9 None => return Vec::new(),
13 Some(it) => it, 10 Some(it) => it,
14 }; 11 };
15 let nav = NavigationTarget::from_module_to_decl(db, module); 12 let nav = NavigationTarget::from_module_to_decl(db, module);
16 Ok(vec![nav]) 13 vec![nav]
17} 14}
18 15
19#[cfg(test)] 16#[cfg(test)]
diff --git a/crates/ra_ide_api/src/runnables.rs b/crates/ra_ide_api/src/runnables.rs
index a3207fdd2..0f9f8deb3 100644
--- a/crates/ra_ide_api/src/runnables.rs
+++ b/crates/ra_ide_api/src/runnables.rs
@@ -3,7 +3,7 @@ use ra_syntax::{
3 TextRange, SyntaxNode, 3 TextRange, SyntaxNode,
4 ast::{self, AstNode, NameOwner, ModuleItemOwner}, 4 ast::{self, AstNode, NameOwner, ModuleItemOwner},
5}; 5};
6use ra_db::{Cancelable, SyntaxDatabase}; 6use ra_db::SyntaxDatabase;
7 7
8use crate::{db::RootDatabase, FileId}; 8use crate::{db::RootDatabase, FileId};
9 9
@@ -21,14 +21,13 @@ pub enum RunnableKind {
21 Bin, 21 Bin,
22} 22}
23 23
24pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Cancelable<Vec<Runnable>> { 24pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec<Runnable> {
25 let source_file = db.source_file(file_id); 25 let source_file = db.source_file(file_id);
26 let res = source_file 26 source_file
27 .syntax() 27 .syntax()
28 .descendants() 28 .descendants()
29 .filter_map(|i| runnable(db, file_id, i)) 29 .filter_map(|i| runnable(db, file_id, i))
30 .collect(); 30 .collect()
31 Ok(res)
32} 31}
33 32
34fn runnable(db: &RootDatabase, file_id: FileId, item: &SyntaxNode) -> Option<Runnable> { 33fn runnable(db: &RootDatabase, file_id: FileId, item: &SyntaxNode) -> Option<Runnable> {