diff options
Diffstat (limited to 'crates')
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 | ||
24 | pub type Cancelable<T> = Result<T, Canceled>; | ||
25 | |||
26 | impl Canceled { | 24 | impl 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; | |||
10 | use ra_syntax::{TextUnit, TextRange, SourceFile, TreeArc}; | 10 | use ra_syntax::{TextUnit, TextRange, SourceFile, TreeArc}; |
11 | 11 | ||
12 | pub use crate::{ | 12 | pub 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 @@ | |||
1 | use std::sync::Arc; | 1 | use std::sync::Arc; |
2 | 2 | ||
3 | use ra_db::Cancelable; | ||
4 | use ra_syntax::{ | 3 | use 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 @@ | |||
1 | use std::sync::Arc; | 1 | use std::sync::Arc; |
2 | 2 | ||
3 | use relative_path::RelativePathBuf; | 3 | use relative_path::RelativePathBuf; |
4 | use ra_db::{CrateId, Cancelable, FileId}; | 4 | use ra_db::{CrateId, FileId}; |
5 | use ra_syntax::{ast, TreeArc, SyntaxNode}; | 5 | use ra_syntax::{ast, TreeArc, SyntaxNode}; |
6 | 6 | ||
7 | use crate::{ | 7 | use 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 @@ | |||
1 | use ra_db::{Cancelable, SourceRootId, FileId}; | 1 | use ra_db::{SourceRootId, FileId}; |
2 | use ra_syntax::{ast, SyntaxNode, AstNode, TreeArc}; | 2 | use ra_syntax::{ast, SyntaxNode, AstNode, TreeArc}; |
3 | 3 | ||
4 | use crate::{ | 4 | use 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 @@ | |||
1 | use std::sync::Arc; | 1 | use std::sync::Arc; |
2 | 2 | ||
3 | use ra_syntax::{SyntaxNode, TreeArc, SourceFile}; | 3 | use ra_syntax::{SyntaxNode, TreeArc, SourceFile}; |
4 | use ra_db::{SourceRootId, LocationIntener, SyntaxDatabase, Cancelable}; | 4 | use ra_db::{SourceRootId, LocationIntener, SyntaxDatabase}; |
5 | 5 | ||
6 | use crate::{ | 6 | use 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 | ||
8 | macro_rules! ctry { | ||
9 | ($expr:expr) => { | ||
10 | match $expr { | ||
11 | None => return Ok(None), | ||
12 | Some(it) => it, | ||
13 | } | ||
14 | }; | ||
15 | } | ||
16 | |||
17 | pub mod db; | 8 | pub mod db; |
18 | #[cfg(test)] | 9 | #[cfg(test)] |
19 | mod mock; | 10 | mod 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; | |||
30 | use join_to_string::join; | 30 | use join_to_string::join; |
31 | use rustc_hash::FxHashMap; | 31 | use rustc_hash::FxHashMap; |
32 | 32 | ||
33 | use ra_db::Cancelable; | ||
34 | |||
35 | use crate::{ | 33 | use 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 | ||
44 | fn 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)] |
54 | pub struct TypeVarId(u32); | 44 | pub 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. |
448 | fn type_for_fn(db: &impl HirDatabase, f: Function) -> Cancelable<Ty> { | 435 | fn 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 | ||
463 | fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Cancelable<Ty> { | 450 | fn 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 | ||
470 | pub(crate) fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Cancelable<Ty> { | 457 | pub(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 | ||
477 | pub(crate) fn type_for_enum_variant(db: &impl HirDatabase, ev: EnumVariant) -> Cancelable<Ty> { | 464 | pub(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 | ||
483 | pub(super) fn type_for_def(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Ty> { | 470 | pub(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 | ||
505 | pub(super) fn type_for_field( | 492 | pub(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 | ||
1205 | pub fn infer(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Arc<InferenceResult>> { | 1179 | pub 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 | ||
7 | use rustc_hash::FxHashMap; | 7 | use rustc_hash::FxHashMap; |
8 | 8 | ||
9 | use ra_db::{Cancelable, SourceRootId}; | 9 | use ra_db::SourceRootId; |
10 | 10 | ||
11 | use crate::{HirDatabase, DefId, module_tree::ModuleId, Module, Crate, Name, Function, impl_block::{ImplId, ImplBlock, ImplItem}}; | 11 | use crate::{HirDatabase, DefId, module_tree::ModuleId, Module, Crate, Name, Function, impl_block::{ImplId, ImplBlock, ImplItem}}; |
12 | use super::Ty; | 12 | use 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 @@ | |||
1 | use std::cmp::{max, min}; | 1 | use std::cmp::{max, min}; |
2 | 2 | ||
3 | use ra_db::{SyntaxDatabase, Cancelable}; | 3 | use ra_db::SyntaxDatabase; |
4 | use ra_syntax::{ | 4 | use 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::{ | |||
11 | use crate::{FilePosition, CallInfo, db::RootDatabase}; | 11 | use 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. |
14 | pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Cancelable<Option<CallInfo>> { | 14 | pub(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 | ||
67 | enum FnCallNode<'a> { | 69 | enum 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 | ||
13 | use crate::{ | 13 | use 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). |
46 | pub(crate) fn completions( | 46 | pub(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 @@ | |||
1 | use hir::{Ty, Def}; | 1 | use hir::{Ty, Def}; |
2 | 2 | ||
3 | use crate::Cancelable; | ||
4 | use crate::completion::{CompletionContext, Completions, CompletionKind, CompletionItem, CompletionItemKind}; | 3 | use 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). |
7 | pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) -> Cancelable<()> { | 6 | pub(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 | ||
26 | fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) -> Cancelable<()> { | 24 | fn 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 | ||
59 | fn complete_methods( | 56 | fn 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 @@ | |||
1 | use crate::{ | 1 | use crate::{ |
2 | Cancelable, | ||
3 | completion::{CompletionItem, CompletionItemKind, Completions, CompletionKind, CompletionContext}, | 2 | completion::{CompletionItem, CompletionItemKind, Completions, CompletionKind, CompletionContext}, |
4 | }; | 3 | }; |
5 | 4 | ||
6 | pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) -> Cancelable<()> { | 5 | pub(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 @@ | |||
1 | use rustc_hash::FxHashSet; | 1 | use rustc_hash::FxHashSet; |
2 | use ra_syntax::TextUnit; | 2 | use ra_syntax::TextUnit; |
3 | 3 | ||
4 | use crate::{ | 4 | use crate::completion::{CompletionItem, CompletionItemKind, Completions, CompletionKind, CompletionContext}; |
5 | Cancelable, | ||
6 | completion::{CompletionItem, CompletionItemKind, Completions, CompletionKind, CompletionContext}, | ||
7 | }; | ||
8 | 5 | ||
9 | pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) -> Cancelable<()> { | 6 | pub(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 | ||
46 | fn complete_fn(acc: &mut Completions, scopes: &hir::ScopesWithSyntaxMapping, offset: TextUnit) { | 42 | fn 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 | }; |
8 | use hir::source_binder; | 8 | use hir::source_binder; |
9 | 9 | ||
10 | use crate::{db, FilePosition, Cancelable}; | 10 | use 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 @@ | |||
1 | use ra_db::{FileId, Cancelable, SyntaxDatabase}; | 1 | use ra_db::{FileId, SyntaxDatabase}; |
2 | use ra_syntax::{ | 2 | use 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}; | |||
9 | pub(crate) fn goto_definition( | 9 | pub(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 | ||
29 | pub(crate) enum ReferenceResult { | 26 | pub(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 | ||
105 | fn name_definition( | 102 | fn 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 @@ | |||
1 | use ra_db::{Cancelable, SyntaxDatabase}; | 1 | use ra_db::{SyntaxDatabase}; |
2 | use ra_syntax::{ | 2 | use 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 | ||
8 | use crate::{db::RootDatabase, RangeInfo, FilePosition, FileRange, NavigationTarget}; | 8 | use crate::{db::RootDatabase, RangeInfo, FilePosition, FileRange, NavigationTarget}; |
9 | 9 | ||
10 | pub(crate) fn hover( | 10 | pub(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 | ||
60 | pub(crate) fn type_of(db: &RootDatabase, frange: FileRange) -> Cancelable<Option<String>> { | 56 | pub(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`. |
89 | fn doc_text_for(db: &RootDatabase, nav: NavigationTarget) -> Cancelable<Option<String>> { | 81 | fn 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 | ||
100 | impl NavigationTarget { | 90 | impl 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. |
12 | macro_rules! ctry { | ||
13 | ($expr:expr) => { | ||
14 | match $expr { | ||
15 | None => return Ok(None), | ||
16 | Some(it) => it, | ||
17 | } | ||
18 | }; | ||
19 | } | ||
20 | |||
21 | mod db; | 12 | mod db; |
22 | mod imp; | 13 | mod imp; |
23 | pub mod mock_analysis; | 14 | pub 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 | }; |
60 | pub use ra_db::{ | 51 | pub use ra_db::{ |
61 | Cancelable, Canceled, CrateGraph, CrateId, FileId, FilePosition, FileRange, SourceRootId | 52 | Canceled, CrateGraph, CrateId, FileId, FilePosition, FileRange, SourceRootId |
62 | }; | 53 | }; |
63 | 54 | ||
55 | pub type Cancelable<T> = Result<T, Canceled>; | ||
56 | |||
64 | #[derive(Default)] | 57 | #[derive(Default)] |
65 | pub struct AnalysisChange { | 58 | pub 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 @@ | |||
1 | use ra_db::{Cancelable, FilePosition}; | 1 | use ra_db::FilePosition; |
2 | 2 | ||
3 | use crate::{NavigationTarget, db::RootDatabase}; | 3 | use 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. |
7 | pub(crate) fn parent_module( | 7 | pub(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 | }; |
6 | use ra_db::{Cancelable, SyntaxDatabase}; | 6 | use ra_db::SyntaxDatabase; |
7 | 7 | ||
8 | use crate::{db::RootDatabase, FileId}; | 8 | use crate::{db::RootDatabase, FileId}; |
9 | 9 | ||
@@ -21,14 +21,13 @@ pub enum RunnableKind { | |||
21 | Bin, | 21 | Bin, |
22 | } | 22 | } |
23 | 23 | ||
24 | pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Cancelable<Vec<Runnable>> { | 24 | pub(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 | ||
34 | fn runnable(db: &RootDatabase, file_id: FileId, item: &SyntaxNode) -> Option<Runnable> { | 33 | fn runnable(db: &RootDatabase, file_id: FileId, item: &SyntaxNode) -> Option<Runnable> { |