aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_assists/src/assists/add_custom_impl.rs7
-rw-r--r--crates/ra_cargo_watch/src/lib.rs13
-rw-r--r--crates/ra_cli/src/analysis_stats.rs1
-rw-r--r--crates/ra_cli/src/main.rs2
-rw-r--r--crates/ra_hir/src/code_model.rs88
-rw-r--r--crates/ra_hir/src/lib.rs4
-rw-r--r--crates/ra_hir/src/source_analyzer.rs (renamed from crates/ra_hir/src/source_binder.rs)195
-rw-r--r--crates/ra_hir_ty/src/infer/expr.rs19
-rw-r--r--crates/ra_hir_ty/src/infer/path.rs9
-rw-r--r--crates/ra_hir_ty/src/method_resolution.rs106
-rw-r--r--crates/ra_hir_ty/src/traits.rs44
-rw-r--r--crates/ra_ide/src/call_hierarchy.rs2
-rw-r--r--crates/ra_ide/src/call_info.rs59
-rw-r--r--crates/ra_ide/src/completion/complete_dot.rs20
-rw-r--r--crates/ra_ide/src/completion/complete_path.rs28
-rw-r--r--crates/ra_ide/src/extend_selection.rs2
-rw-r--r--crates/ra_ide/src/references.rs13
-rw-r--r--crates/ra_ide/src/references/search_scope.rs3
-rw-r--r--crates/ra_lsp_server/src/main.rs4
-rw-r--r--crates/ra_lsp_server/src/main_loop.rs1
-rw-r--r--crates/ra_lsp_server/src/main_loop/handlers.rs1
-rw-r--r--crates/ra_syntax/src/ast/expr_extensions.rs4
-rw-r--r--crates/ra_syntax/src/validation.rs61
23 files changed, 396 insertions, 290 deletions
diff --git a/crates/ra_assists/src/assists/add_custom_impl.rs b/crates/ra_assists/src/assists/add_custom_impl.rs
index 037306fd6..52e8c693d 100644
--- a/crates/ra_assists/src/assists/add_custom_impl.rs
+++ b/crates/ra_assists/src/assists/add_custom_impl.rs
@@ -10,7 +10,7 @@ use ra_syntax::{
10 TextRange, TextUnit, 10 TextRange, TextUnit,
11}; 11};
12 12
13const DERIVE_TRAIT: &'static str = "derive"; 13const DERIVE_TRAIT: &str = "derive";
14 14
15// Assist: add_custom_impl 15// Assist: add_custom_impl
16// 16//
@@ -49,7 +49,10 @@ pub(crate) fn add_custom_impl(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist
49 let annotated_name = annotated.syntax().text().to_string(); 49 let annotated_name = annotated.syntax().text().to_string();
50 let start_offset = annotated.syntax().parent()?.text_range().end(); 50 let start_offset = annotated.syntax().parent()?.text_range().end();
51 51
52 ctx.add_assist(AssistId("add_custom_impl"), "add custom impl", |edit| { 52 let label =
53 format!("Add Custom impl '{}' for '{}'", trait_token.text().as_str(), annotated_name);
54
55 ctx.add_assist(AssistId("add_custom_impl"), label, |edit| {
53 edit.target(attr.syntax().text_range()); 56 edit.target(attr.syntax().text_range());
54 57
55 let new_attr_input = input 58 let new_attr_input = input
diff --git a/crates/ra_cargo_watch/src/lib.rs b/crates/ra_cargo_watch/src/lib.rs
index cb0856aa4..20fa5a924 100644
--- a/crates/ra_cargo_watch/src/lib.rs
+++ b/crates/ra_cargo_watch/src/lib.rs
@@ -184,8 +184,13 @@ impl CheckWatcherState {
184 workspace_root: PathBuf, 184 workspace_root: PathBuf,
185 shared: Arc<RwLock<CheckWatcherSharedState>>, 185 shared: Arc<RwLock<CheckWatcherSharedState>>,
186 ) -> CheckWatcherState { 186 ) -> CheckWatcherState {
187 let watcher = WatchThread::new(&options, &workspace_root); 187 CheckWatcherState {
188 CheckWatcherState { options, workspace_root, watcher, last_update_req: None, shared } 188 options,
189 workspace_root,
190 watcher: WatchThread::dummy(),
191 last_update_req: None,
192 shared,
193 }
189 } 194 }
190 195
191 fn run(&mut self, task_send: &Sender<CheckTask>, cmd_recv: &Receiver<CheckCommand>) { 196 fn run(&mut self, task_send: &Sender<CheckTask>, cmd_recv: &Receiver<CheckCommand>) {
@@ -313,6 +318,10 @@ enum CheckEvent {
313} 318}
314 319
315impl WatchThread { 320impl WatchThread {
321 fn dummy() -> WatchThread {
322 WatchThread { handle: None, message_recv: never() }
323 }
324
316 fn new(options: &CheckOptions, workspace_root: &PathBuf) -> WatchThread { 325 fn new(options: &CheckOptions, workspace_root: &PathBuf) -> WatchThread {
317 let mut args: Vec<String> = vec![ 326 let mut args: Vec<String> = vec![
318 options.command.clone(), 327 options.command.clone(),
diff --git a/crates/ra_cli/src/analysis_stats.rs b/crates/ra_cli/src/analysis_stats.rs
index ac65415a5..fd0027691 100644
--- a/crates/ra_cli/src/analysis_stats.rs
+++ b/crates/ra_cli/src/analysis_stats.rs
@@ -183,7 +183,6 @@ pub fn run(
183 println!("Total: {:?}, {}", analysis_time.elapsed(), ra_prof::memory_usage()); 183 println!("Total: {:?}, {}", analysis_time.elapsed(), ra_prof::memory_usage());
184 184
185 if memory_usage { 185 if memory_usage {
186 drop(db);
187 for (name, bytes) in host.per_query_memory_usage() { 186 for (name, bytes) in host.per_query_memory_usage() {
188 println!("{:>8} {}", bytes, name) 187 println!("{:>8} {}", bytes, name)
189 } 188 }
diff --git a/crates/ra_cli/src/main.rs b/crates/ra_cli/src/main.rs
index 3808590ab..806612c2c 100644
--- a/crates/ra_cli/src/main.rs
+++ b/crates/ra_cli/src/main.rs
@@ -22,7 +22,7 @@ pub enum Verbosity {
22} 22}
23 23
24impl Verbosity { 24impl Verbosity {
25 fn is_verbose(&self) -> bool { 25 fn is_verbose(self) -> bool {
26 match self { 26 match self {
27 Verbosity::Verbose => true, 27 Verbosity::Verbose => true,
28 _ => false, 28 _ => false,
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index a177cebca..3b479356f 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -21,8 +21,8 @@ use hir_expand::{
21 MacroDefId, 21 MacroDefId,
22}; 22};
23use hir_ty::{ 23use hir_ty::{
24 autoderef, display::HirFormatter, expr::ExprValidator, ApplicationTy, Canonical, InEnvironment, 24 autoderef, display::HirFormatter, expr::ExprValidator, method_resolution, ApplicationTy,
25 TraitEnvironment, Ty, TyDefId, TypeCtor, TypeWalk, 25 Canonical, InEnvironment, TraitEnvironment, Ty, TyDefId, TypeCtor, TypeWalk,
26}; 26};
27use ra_db::{CrateId, Edition, FileId}; 27use ra_db::{CrateId, Edition, FileId};
28use ra_prof::profile; 28use ra_prof::profile;
@@ -120,7 +120,8 @@ impl_froms!(
120 BuiltinType 120 BuiltinType
121); 121);
122 122
123pub use hir_def::{attr::Attrs, visibility::Visibility}; 123pub use hir_def::{attr::Attrs, visibility::Visibility, AssocItemId};
124use rustc_hash::FxHashSet;
124 125
125impl Module { 126impl Module {
126 pub(crate) fn new(krate: Crate, crate_module_id: LocalModuleId) -> Module { 127 pub(crate) fn new(krate: Crate, crate_module_id: LocalModuleId) -> Module {
@@ -878,6 +879,28 @@ impl Type {
878 } 879 }
879 } 880 }
880 881
882 /// Checks that particular type `ty` implements `std::future::Future`.
883 /// This function is used in `.await` syntax completion.
884 pub fn impls_future(&self, db: &impl HirDatabase) -> bool {
885 let krate = self.krate;
886
887 let std_future_trait =
888 db.lang_item(krate, "future_trait".into()).and_then(|it| it.as_trait());
889 let std_future_trait = match std_future_trait {
890 Some(it) => it,
891 None => return false,
892 };
893
894 let canonical_ty = Canonical { value: self.ty.value.clone(), num_vars: 0 };
895 method_resolution::implements_trait(
896 &canonical_ty,
897 db,
898 self.ty.environment.clone(),
899 krate,
900 std_future_trait,
901 )
902 }
903
881 // FIXME: this method is broken, as it doesn't take closures into account. 904 // FIXME: this method is broken, as it doesn't take closures into account.
882 pub fn as_callable(&self) -> Option<CallableDef> { 905 pub fn as_callable(&self) -> Option<CallableDef> {
883 Some(self.ty.value.as_callable()?.0) 906 Some(self.ty.value.as_callable()?.0)
@@ -986,6 +1009,65 @@ impl Type {
986 None 1009 None
987 } 1010 }
988 1011
1012 pub fn iterate_method_candidates<T>(
1013 &self,
1014 db: &impl HirDatabase,
1015 krate: Crate,
1016 traits_in_scope: &FxHashSet<TraitId>,
1017 name: Option<&Name>,
1018 mut callback: impl FnMut(&Ty, Function) -> Option<T>,
1019 ) -> Option<T> {
1020 // There should be no inference vars in types passed here
1021 // FIXME check that?
1022 // FIXME replace Unknown by bound vars here
1023 let canonical = Canonical { value: self.ty.value.clone(), num_vars: 0 };
1024
1025 let env = self.ty.environment.clone();
1026 let krate = krate.id;
1027
1028 method_resolution::iterate_method_candidates(
1029 &canonical,
1030 db,
1031 env,
1032 krate,
1033 traits_in_scope,
1034 name,
1035 method_resolution::LookupMode::MethodCall,
1036 |ty, it| match it {
1037 AssocItemId::FunctionId(f) => callback(ty, f.into()),
1038 _ => None,
1039 },
1040 )
1041 }
1042
1043 pub fn iterate_path_candidates<T>(
1044 &self,
1045 db: &impl HirDatabase,
1046 krate: Crate,
1047 traits_in_scope: &FxHashSet<TraitId>,
1048 name: Option<&Name>,
1049 mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>,
1050 ) -> Option<T> {
1051 // There should be no inference vars in types passed here
1052 // FIXME check that?
1053 // FIXME replace Unknown by bound vars here
1054 let canonical = Canonical { value: self.ty.value.clone(), num_vars: 0 };
1055
1056 let env = self.ty.environment.clone();
1057 let krate = krate.id;
1058
1059 method_resolution::iterate_method_candidates(
1060 &canonical,
1061 db,
1062 env,
1063 krate,
1064 traits_in_scope,
1065 name,
1066 method_resolution::LookupMode::Path,
1067 |ty, it| callback(ty, it.into()),
1068 )
1069 }
1070
989 pub fn as_adt(&self) -> Option<Adt> { 1071 pub fn as_adt(&self) -> Option<Adt> {
990 let (adt, _subst) = self.ty.value.as_adt()?; 1072 let (adt, _subst) = self.ty.value.as_adt()?;
991 Some(adt.into()) 1073 Some(adt.into())
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index 3d13978d4..a1cf89010 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -27,7 +27,7 @@ macro_rules! impl_froms {
27} 27}
28 28
29pub mod db; 29pub mod db;
30pub mod source_binder; 30pub mod source_analyzer;
31 31
32pub mod diagnostics; 32pub mod diagnostics;
33 33
@@ -46,7 +46,7 @@ pub use crate::{
46 }, 46 },
47 from_source::FromSource, 47 from_source::FromSource,
48 has_source::HasSource, 48 has_source::HasSource,
49 source_binder::{PathResolution, ScopeEntryWithSyntax, SourceAnalyzer}, 49 source_analyzer::{PathResolution, ScopeEntryWithSyntax, SourceAnalyzer},
50}; 50};
51 51
52pub use hir_def::{ 52pub use hir_def::{
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_analyzer.rs
index a2a9d968c..76e0bff34 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_analyzer.rs
@@ -15,17 +15,13 @@ use hir_def::{
15 }, 15 },
16 expr::{ExprId, PatId}, 16 expr::{ExprId, PatId},
17 nameres::ModuleSource, 17 nameres::ModuleSource,
18 path::path,
19 resolver::{self, resolver_for_scope, HasResolver, Resolver, TypeNs, ValueNs}, 18 resolver::{self, resolver_for_scope, HasResolver, Resolver, TypeNs, ValueNs},
20 AssocItemId, DefWithBodyId, 19 DefWithBodyId, TraitId,
21}; 20};
22use hir_expand::{ 21use hir_expand::{
23 hygiene::Hygiene, name::AsName, AstId, HirFileId, InFile, MacroCallId, MacroCallKind, 22 hygiene::Hygiene, name::AsName, AstId, HirFileId, InFile, MacroCallId, MacroCallKind,
24}; 23};
25use hir_ty::{ 24use hir_ty::{InEnvironment, InferenceResult, TraitEnvironment};
26 method_resolution::{self, implements_trait},
27 Canonical, InEnvironment, InferenceResult, TraitEnvironment, Ty,
28};
29use ra_prof::profile; 25use ra_prof::profile;
30use ra_syntax::{ 26use ra_syntax::{
31 ast::{self, AstNode}, 27 ast::{self, AstNode},
@@ -33,71 +29,13 @@ use ra_syntax::{
33 SyntaxKind::*, 29 SyntaxKind::*,
34 SyntaxNode, SyntaxNodePtr, SyntaxToken, TextRange, TextUnit, 30 SyntaxNode, SyntaxNodePtr, SyntaxToken, TextRange, TextUnit,
35}; 31};
32use rustc_hash::FxHashSet;
36 33
37use crate::{ 34use crate::{
38 db::HirDatabase, Adt, AssocItem, Const, DefWithBody, Enum, EnumVariant, FromSource, Function, 35 db::HirDatabase, Adt, Const, DefWithBody, Enum, EnumVariant, FromSource, Function, ImplBlock,
39 ImplBlock, Local, MacroDef, Name, Path, ScopeDef, Static, Struct, Trait, Type, TypeAlias, 36 Local, MacroDef, Name, Path, ScopeDef, Static, Struct, Trait, Type, TypeAlias, TypeParam,
40 TypeParam,
41}; 37};
42 38
43fn try_get_resolver_for_node(db: &impl HirDatabase, node: InFile<&SyntaxNode>) -> Option<Resolver> {
44 match_ast! {
45 match (node.value) {
46 ast::Module(it) => {
47 let src = node.with_value(it);
48 Some(crate::Module::from_declaration(db, src)?.id.resolver(db))
49 },
50 ast::SourceFile(it) => {
51 let src = node.with_value(ModuleSource::SourceFile(it));
52 Some(crate::Module::from_definition(db, src)?.id.resolver(db))
53 },
54 ast::StructDef(it) => {
55 let src = node.with_value(it);
56 Some(Struct::from_source(db, src)?.id.resolver(db))
57 },
58 ast::EnumDef(it) => {
59 let src = node.with_value(it);
60 Some(Enum::from_source(db, src)?.id.resolver(db))
61 },
62 ast::ImplBlock(it) => {
63 let src = node.with_value(it);
64 Some(ImplBlock::from_source(db, src)?.id.resolver(db))
65 },
66 ast::TraitDef(it) => {
67 let src = node.with_value(it);
68 Some(Trait::from_source(db, src)?.id.resolver(db))
69 },
70 _ => match node.value.kind() {
71 FN_DEF | CONST_DEF | STATIC_DEF => {
72 let def = def_with_body_from_child_node(db, node)?;
73 let def = DefWithBodyId::from(def);
74 Some(def.resolver(db))
75 }
76 // FIXME add missing cases
77 _ => None
78 }
79 }
80 }
81}
82
83fn def_with_body_from_child_node(
84 db: &impl HirDatabase,
85 child: InFile<&SyntaxNode>,
86) -> Option<DefWithBody> {
87 let _p = profile("def_with_body_from_child_node");
88 child.cloned().ancestors_with_macros(db).find_map(|node| {
89 let n = &node.value;
90 match_ast! {
91 match n {
92 ast::FnDef(def) => { return Function::from_source(db, node.with_value(def)).map(DefWithBody::from); },
93 ast::ConstDef(def) => { return Const::from_source(db, node.with_value(def)).map(DefWithBody::from); },
94 ast::StaticDef(def) => { return Static::from_source(db, node.with_value(def)).map(DefWithBody::from); },
95 _ => { None },
96 }
97 }
98 })
99}
100
101/// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of 39/// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of
102/// original source files. It should not be used inside the HIR itself. 40/// original source files. It should not be used inside the HIR itself.
103#[derive(Debug)] 41#[derive(Debug)]
@@ -409,68 +347,9 @@ impl SourceAnalyzer {
409 .collect() 347 .collect()
410 } 348 }
411 349
412 pub fn iterate_method_candidates<T>( 350 /// Note: `FxHashSet<TraitId>` should be treated as an opaque type, passed into `Type
413 &self, 351 pub fn traits_in_scope(&self, db: &impl HirDatabase) -> FxHashSet<TraitId> {
414 db: &impl HirDatabase, 352 self.resolver.traits_in_scope(db)
415 ty: &Type,
416 name: Option<&Name>,
417 mut callback: impl FnMut(&Ty, Function) -> Option<T>,
418 ) -> Option<T> {
419 // There should be no inference vars in types passed here
420 // FIXME check that?
421 // FIXME replace Unknown by bound vars here
422 let canonical = Canonical { value: ty.ty.value.clone(), num_vars: 0 };
423 method_resolution::iterate_method_candidates(
424 &canonical,
425 db,
426 &self.resolver,
427 name,
428 method_resolution::LookupMode::MethodCall,
429 |ty, it| match it {
430 AssocItemId::FunctionId(f) => callback(ty, f.into()),
431 _ => None,
432 },
433 )
434 }
435
436 pub fn iterate_path_candidates<T>(
437 &self,
438 db: &impl HirDatabase,
439 ty: &Type,
440 name: Option<&Name>,
441 mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>,
442 ) -> Option<T> {
443 // There should be no inference vars in types passed here
444 // FIXME check that?
445 // FIXME replace Unknown by bound vars here
446 let canonical = Canonical { value: ty.ty.value.clone(), num_vars: 0 };
447 method_resolution::iterate_method_candidates(
448 &canonical,
449 db,
450 &self.resolver,
451 name,
452 method_resolution::LookupMode::Path,
453 |ty, it| callback(ty, it.into()),
454 )
455 }
456
457 /// Checks that particular type `ty` implements `std::future::Future`.
458 /// This function is used in `.await` syntax completion.
459 pub fn impls_future(&self, db: &impl HirDatabase, ty: Type) -> bool {
460 let std_future_path = path![std::future::Future];
461
462 let std_future_trait = match self.resolver.resolve_known_trait(db, &std_future_path) {
463 Some(it) => it.into(),
464 _ => return false,
465 };
466
467 let krate = match self.resolver.krate() {
468 Some(krate) => krate,
469 _ => return false,
470 };
471
472 let canonical_ty = Canonical { value: ty.ty.value, num_vars: 0 };
473 implements_trait(&canonical_ty, db, &self.resolver, krate.into(), std_future_trait)
474 } 353 }
475 354
476 pub fn expand( 355 pub fn expand(
@@ -487,6 +366,64 @@ impl SourceAnalyzer {
487 } 366 }
488} 367}
489 368
369fn try_get_resolver_for_node(db: &impl HirDatabase, node: InFile<&SyntaxNode>) -> Option<Resolver> {
370 match_ast! {
371 match (node.value) {
372 ast::Module(it) => {
373 let src = node.with_value(it);
374 Some(crate::Module::from_declaration(db, src)?.id.resolver(db))
375 },
376 ast::SourceFile(it) => {
377 let src = node.with_value(ModuleSource::SourceFile(it));
378 Some(crate::Module::from_definition(db, src)?.id.resolver(db))
379 },
380 ast::StructDef(it) => {
381 let src = node.with_value(it);
382 Some(Struct::from_source(db, src)?.id.resolver(db))
383 },
384 ast::EnumDef(it) => {
385 let src = node.with_value(it);
386 Some(Enum::from_source(db, src)?.id.resolver(db))
387 },
388 ast::ImplBlock(it) => {
389 let src = node.with_value(it);
390 Some(ImplBlock::from_source(db, src)?.id.resolver(db))
391 },
392 ast::TraitDef(it) => {
393 let src = node.with_value(it);
394 Some(Trait::from_source(db, src)?.id.resolver(db))
395 },
396 _ => match node.value.kind() {
397 FN_DEF | CONST_DEF | STATIC_DEF => {
398 let def = def_with_body_from_child_node(db, node)?;
399 let def = DefWithBodyId::from(def);
400 Some(def.resolver(db))
401 }
402 // FIXME add missing cases
403 _ => None
404 }
405 }
406 }
407}
408
409fn def_with_body_from_child_node(
410 db: &impl HirDatabase,
411 child: InFile<&SyntaxNode>,
412) -> Option<DefWithBody> {
413 let _p = profile("def_with_body_from_child_node");
414 child.cloned().ancestors_with_macros(db).find_map(|node| {
415 let n = &node.value;
416 match_ast! {
417 match n {
418 ast::FnDef(def) => { return Function::from_source(db, node.with_value(def)).map(DefWithBody::from); },
419 ast::ConstDef(def) => { return Const::from_source(db, node.with_value(def)).map(DefWithBody::from); },
420 ast::StaticDef(def) => { return Static::from_source(db, node.with_value(def)).map(DefWithBody::from); },
421 _ => { None },
422 }
423 }
424 })
425}
426
490fn scope_for( 427fn scope_for(
491 scopes: &ExprScopes, 428 scopes: &ExprScopes,
492 source_map: &BodySourceMap, 429 source_map: &BodySourceMap,
diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs
index 3af05394c..d6a17e469 100644
--- a/crates/ra_hir_ty/src/infer/expr.rs
+++ b/crates/ra_hir_ty/src/infer/expr.rs
@@ -569,12 +569,19 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
569 ) -> Ty { 569 ) -> Ty {
570 let receiver_ty = self.infer_expr(receiver, &Expectation::none()); 570 let receiver_ty = self.infer_expr(receiver, &Expectation::none());
571 let canonicalized_receiver = self.canonicalizer().canonicalize_ty(receiver_ty.clone()); 571 let canonicalized_receiver = self.canonicalizer().canonicalize_ty(receiver_ty.clone());
572 let resolved = method_resolution::lookup_method( 572
573 &canonicalized_receiver.value, 573 let traits_in_scope = self.resolver.traits_in_scope(self.db);
574 self.db, 574
575 method_name, 575 let resolved = self.resolver.krate().and_then(|krate| {
576 &self.resolver, 576 method_resolution::lookup_method(
577 ); 577 &canonicalized_receiver.value,
578 self.db,
579 self.trait_env.clone(),
580 krate,
581 &traits_in_scope,
582 method_name,
583 )
584 });
578 let (derefed_receiver_ty, method_ty, def_generics) = match resolved { 585 let (derefed_receiver_ty, method_ty, def_generics) = match resolved {
579 Some((ty, func)) => { 586 Some((ty, func)) => {
580 let ty = canonicalized_receiver.decanonicalize_ty(ty); 587 let ty = canonicalized_receiver.decanonicalize_ty(ty);
diff --git a/crates/ra_hir_ty/src/infer/path.rs b/crates/ra_hir_ty/src/infer/path.rs
index ffd358367..2c1d4831d 100644
--- a/crates/ra_hir_ty/src/infer/path.rs
+++ b/crates/ra_hir_ty/src/infer/path.rs
@@ -11,7 +11,7 @@ use hir_expand::name::Name;
11 11
12use crate::{db::HirDatabase, method_resolution, Substs, Ty, TypeWalk, ValueTyDefId}; 12use crate::{db::HirDatabase, method_resolution, Substs, Ty, TypeWalk, ValueTyDefId};
13 13
14use super::{ExprOrPatId, InferenceContext, TraitRef}; 14use super::{ExprOrPatId, InferenceContext, TraitEnvironment, TraitRef};
15 15
16impl<'a, D: HirDatabase> InferenceContext<'a, D> { 16impl<'a, D: HirDatabase> InferenceContext<'a, D> {
17 pub(super) fn infer_path( 17 pub(super) fn infer_path(
@@ -193,11 +193,16 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
193 } 193 }
194 194
195 let canonical_ty = self.canonicalizer().canonicalize_ty(ty.clone()); 195 let canonical_ty = self.canonicalizer().canonicalize_ty(ty.clone());
196 let env = TraitEnvironment::lower(self.db, &self.resolver);
197 let krate = self.resolver.krate()?;
198 let traits_in_scope = self.resolver.traits_in_scope(self.db);
196 199
197 method_resolution::iterate_method_candidates( 200 method_resolution::iterate_method_candidates(
198 &canonical_ty.value, 201 &canonical_ty.value,
199 self.db, 202 self.db,
200 &self.resolver.clone(), 203 env,
204 krate,
205 &traits_in_scope,
201 Some(name), 206 Some(name),
202 method_resolution::LookupMode::Path, 207 method_resolution::LookupMode::Path,
203 move |_ty, item| { 208 move |_ty, item| {
diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs
index 888dc3116..5bacbbd7c 100644
--- a/crates/ra_hir_ty/src/method_resolution.rs
+++ b/crates/ra_hir_ty/src/method_resolution.rs
@@ -6,13 +6,13 @@ use std::sync::Arc;
6 6
7use arrayvec::ArrayVec; 7use arrayvec::ArrayVec;
8use hir_def::{ 8use hir_def::{
9 lang_item::LangItemTarget, resolver::Resolver, type_ref::Mutability, AssocContainerId, 9 lang_item::LangItemTarget, type_ref::Mutability, AssocContainerId, AssocItemId, FunctionId,
10 AssocItemId, FunctionId, HasModule, ImplId, Lookup, TraitId, 10 HasModule, ImplId, Lookup, TraitId,
11}; 11};
12use hir_expand::name::Name; 12use hir_expand::name::Name;
13use ra_db::CrateId; 13use ra_db::CrateId;
14use ra_prof::profile; 14use ra_prof::profile;
15use rustc_hash::FxHashMap; 15use rustc_hash::{FxHashMap, FxHashSet};
16 16
17use super::Substs; 17use super::Substs;
18use crate::{ 18use crate::{
@@ -144,14 +144,24 @@ impl Ty {
144pub(crate) fn lookup_method( 144pub(crate) fn lookup_method(
145 ty: &Canonical<Ty>, 145 ty: &Canonical<Ty>,
146 db: &impl HirDatabase, 146 db: &impl HirDatabase,
147 env: Arc<TraitEnvironment>,
148 krate: CrateId,
149 traits_in_scope: &FxHashSet<TraitId>,
147 name: &Name, 150 name: &Name,
148 resolver: &Resolver,
149) -> Option<(Ty, FunctionId)> { 151) -> Option<(Ty, FunctionId)> {
150 iterate_method_candidates(ty, db, resolver, Some(name), LookupMode::MethodCall, |ty, f| match f 152 iterate_method_candidates(
151 { 153 ty,
152 AssocItemId::FunctionId(f) => Some((ty.clone(), f)), 154 db,
153 _ => None, 155 env,
154 }) 156 krate,
157 &traits_in_scope,
158 Some(name),
159 LookupMode::MethodCall,
160 |ty, f| match f {
161 AssocItemId::FunctionId(f) => Some((ty.clone(), f)),
162 _ => None,
163 },
164 )
155} 165}
156 166
157/// Whether we're looking up a dotted method call (like `v.len()`) or a path 167/// Whether we're looking up a dotted method call (like `v.len()`) or a path
@@ -172,7 +182,9 @@ pub enum LookupMode {
172pub fn iterate_method_candidates<T>( 182pub fn iterate_method_candidates<T>(
173 ty: &Canonical<Ty>, 183 ty: &Canonical<Ty>,
174 db: &impl HirDatabase, 184 db: &impl HirDatabase,
175 resolver: &Resolver, 185 env: Arc<TraitEnvironment>,
186 krate: CrateId,
187 traits_in_scope: &FxHashSet<TraitId>,
176 name: Option<&Name>, 188 name: Option<&Name>,
177 mode: LookupMode, 189 mode: LookupMode,
178 mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, 190 mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>,
@@ -187,9 +199,7 @@ pub fn iterate_method_candidates<T>(
187 // Also note that when we've got a receiver like &S, even if the method we 199 // Also note that when we've got a receiver like &S, even if the method we
188 // find in the end takes &self, we still do the autoderef step (just as 200 // find in the end takes &self, we still do the autoderef step (just as
189 // rustc does an autoderef and then autoref again). 201 // rustc does an autoderef and then autoref again).
190 let environment = TraitEnvironment::lower(db, resolver); 202 let ty = InEnvironment { value: ty.clone(), environment: env.clone() };
191 let ty = InEnvironment { value: ty.clone(), environment };
192 let krate = resolver.krate()?;
193 203
194 // We have to be careful about the order we're looking at candidates 204 // We have to be careful about the order we're looking at candidates
195 // in here. Consider the case where we're resolving `x.clone()` 205 // in here. Consider the case where we're resolving `x.clone()`
@@ -209,7 +219,9 @@ pub fn iterate_method_candidates<T>(
209 if let Some(result) = iterate_method_candidates_with_autoref( 219 if let Some(result) = iterate_method_candidates_with_autoref(
210 &deref_chain[i..], 220 &deref_chain[i..],
211 db, 221 db,
212 resolver, 222 env.clone(),
223 krate,
224 traits_in_scope,
213 name, 225 name,
214 &mut callback, 226 &mut callback,
215 ) { 227 ) {
@@ -220,7 +232,15 @@ pub fn iterate_method_candidates<T>(
220 } 232 }
221 LookupMode::Path => { 233 LookupMode::Path => {
222 // No autoderef for path lookups 234 // No autoderef for path lookups
223 iterate_method_candidates_for_self_ty(&ty, db, resolver, name, &mut callback) 235 iterate_method_candidates_for_self_ty(
236 &ty,
237 db,
238 env,
239 krate,
240 traits_in_scope,
241 name,
242 &mut callback,
243 )
224 } 244 }
225 } 245 }
226} 246}
@@ -228,7 +248,9 @@ pub fn iterate_method_candidates<T>(
228fn iterate_method_candidates_with_autoref<T>( 248fn iterate_method_candidates_with_autoref<T>(
229 deref_chain: &[Canonical<Ty>], 249 deref_chain: &[Canonical<Ty>],
230 db: &impl HirDatabase, 250 db: &impl HirDatabase,
231 resolver: &Resolver, 251 env: Arc<TraitEnvironment>,
252 krate: CrateId,
253 traits_in_scope: &FxHashSet<TraitId>,
232 name: Option<&Name>, 254 name: Option<&Name>,
233 mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, 255 mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>,
234) -> Option<T> { 256) -> Option<T> {
@@ -236,7 +258,9 @@ fn iterate_method_candidates_with_autoref<T>(
236 &deref_chain[0], 258 &deref_chain[0],
237 &deref_chain[1..], 259 &deref_chain[1..],
238 db, 260 db,
239 resolver, 261 env.clone(),
262 krate,
263 &traits_in_scope,
240 name, 264 name,
241 &mut callback, 265 &mut callback,
242 ) { 266 ) {
@@ -250,7 +274,9 @@ fn iterate_method_candidates_with_autoref<T>(
250 &refed, 274 &refed,
251 deref_chain, 275 deref_chain,
252 db, 276 db,
253 resolver, 277 env.clone(),
278 krate,
279 &traits_in_scope,
254 name, 280 name,
255 &mut callback, 281 &mut callback,
256 ) { 282 ) {
@@ -264,7 +290,9 @@ fn iterate_method_candidates_with_autoref<T>(
264 &ref_muted, 290 &ref_muted,
265 deref_chain, 291 deref_chain,
266 db, 292 db,
267 resolver, 293 env.clone(),
294 krate,
295 &traits_in_scope,
268 name, 296 name,
269 &mut callback, 297 &mut callback,
270 ) { 298 ) {
@@ -277,14 +305,15 @@ fn iterate_method_candidates_by_receiver<T>(
277 receiver_ty: &Canonical<Ty>, 305 receiver_ty: &Canonical<Ty>,
278 rest_of_deref_chain: &[Canonical<Ty>], 306 rest_of_deref_chain: &[Canonical<Ty>],
279 db: &impl HirDatabase, 307 db: &impl HirDatabase,
280 resolver: &Resolver, 308 env: Arc<TraitEnvironment>,
309 krate: CrateId,
310 traits_in_scope: &FxHashSet<TraitId>,
281 name: Option<&Name>, 311 name: Option<&Name>,
282 mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, 312 mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>,
283) -> Option<T> { 313) -> Option<T> {
284 // We're looking for methods with *receiver* type receiver_ty. These could 314 // We're looking for methods with *receiver* type receiver_ty. These could
285 // be found in any of the derefs of receiver_ty, so we have to go through 315 // be found in any of the derefs of receiver_ty, so we have to go through
286 // that. 316 // that.
287 let krate = resolver.krate()?;
288 for self_ty in std::iter::once(receiver_ty).chain(rest_of_deref_chain) { 317 for self_ty in std::iter::once(receiver_ty).chain(rest_of_deref_chain) {
289 if let Some(result) = 318 if let Some(result) =
290 iterate_inherent_methods(self_ty, db, name, Some(receiver_ty), krate, &mut callback) 319 iterate_inherent_methods(self_ty, db, name, Some(receiver_ty), krate, &mut callback)
@@ -296,7 +325,9 @@ fn iterate_method_candidates_by_receiver<T>(
296 if let Some(result) = iterate_trait_method_candidates( 325 if let Some(result) = iterate_trait_method_candidates(
297 self_ty, 326 self_ty,
298 db, 327 db,
299 resolver, 328 env.clone(),
329 krate,
330 &traits_in_scope,
300 name, 331 name,
301 Some(receiver_ty), 332 Some(receiver_ty),
302 &mut callback, 333 &mut callback,
@@ -310,17 +341,25 @@ fn iterate_method_candidates_by_receiver<T>(
310fn iterate_method_candidates_for_self_ty<T>( 341fn iterate_method_candidates_for_self_ty<T>(
311 self_ty: &Canonical<Ty>, 342 self_ty: &Canonical<Ty>,
312 db: &impl HirDatabase, 343 db: &impl HirDatabase,
313 resolver: &Resolver, 344 env: Arc<TraitEnvironment>,
345 krate: CrateId,
346 traits_in_scope: &FxHashSet<TraitId>,
314 name: Option<&Name>, 347 name: Option<&Name>,
315 mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, 348 mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>,
316) -> Option<T> { 349) -> Option<T> {
317 let krate = resolver.krate()?;
318 if let Some(result) = iterate_inherent_methods(self_ty, db, name, None, krate, &mut callback) { 350 if let Some(result) = iterate_inherent_methods(self_ty, db, name, None, krate, &mut callback) {
319 return Some(result); 351 return Some(result);
320 } 352 }
321 if let Some(result) = 353 if let Some(result) = iterate_trait_method_candidates(
322 iterate_trait_method_candidates(self_ty, db, resolver, name, None, &mut callback) 354 self_ty,
323 { 355 db,
356 env,
357 krate,
358 traits_in_scope,
359 name,
360 None,
361 &mut callback,
362 ) {
324 return Some(result); 363 return Some(result);
325 } 364 }
326 None 365 None
@@ -329,14 +368,13 @@ fn iterate_method_candidates_for_self_ty<T>(
329fn iterate_trait_method_candidates<T>( 368fn iterate_trait_method_candidates<T>(
330 self_ty: &Canonical<Ty>, 369 self_ty: &Canonical<Ty>,
331 db: &impl HirDatabase, 370 db: &impl HirDatabase,
332 resolver: &Resolver, 371 env: Arc<TraitEnvironment>,
372 krate: CrateId,
373 traits_in_scope: &FxHashSet<TraitId>,
333 name: Option<&Name>, 374 name: Option<&Name>,
334 receiver_ty: Option<&Canonical<Ty>>, 375 receiver_ty: Option<&Canonical<Ty>>,
335 mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, 376 mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>,
336) -> Option<T> { 377) -> Option<T> {
337 let krate = resolver.krate()?;
338 // FIXME: maybe put the trait_env behind a query (need to figure out good input parameters for that)
339 let env = TraitEnvironment::lower(db, resolver);
340 // if ty is `impl Trait` or `dyn Trait`, the trait doesn't need to be in scope 378 // if ty is `impl Trait` or `dyn Trait`, the trait doesn't need to be in scope
341 let inherent_trait = self_ty.value.inherent_trait().into_iter(); 379 let inherent_trait = self_ty.value.inherent_trait().into_iter();
342 // if we have `T: Trait` in the param env, the trait doesn't need to be in scope 380 // if we have `T: Trait` in the param env, the trait doesn't need to be in scope
@@ -344,8 +382,7 @@ fn iterate_trait_method_candidates<T>(
344 .trait_predicates_for_self_ty(&self_ty.value) 382 .trait_predicates_for_self_ty(&self_ty.value)
345 .map(|tr| tr.trait_) 383 .map(|tr| tr.trait_)
346 .flat_map(|t| all_super_traits(db, t)); 384 .flat_map(|t| all_super_traits(db, t));
347 let traits = 385 let traits = inherent_trait.chain(traits_from_env).chain(traits_in_scope.iter().copied());
348 inherent_trait.chain(traits_from_env).chain(resolver.traits_in_scope(db).into_iter());
349 'traits: for t in traits { 386 'traits: for t in traits {
350 let data = db.trait_data(t); 387 let data = db.trait_data(t);
351 388
@@ -465,7 +502,7 @@ fn transform_receiver_ty(
465pub fn implements_trait( 502pub fn implements_trait(
466 ty: &Canonical<Ty>, 503 ty: &Canonical<Ty>,
467 db: &impl HirDatabase, 504 db: &impl HirDatabase,
468 resolver: &Resolver, 505 env: Arc<TraitEnvironment>,
469 krate: CrateId, 506 krate: CrateId,
470 trait_: TraitId, 507 trait_: TraitId,
471) -> bool { 508) -> bool {
@@ -474,7 +511,6 @@ pub fn implements_trait(
474 // anyway, but currently Chalk doesn't implement `dyn/impl Trait` yet 511 // anyway, but currently Chalk doesn't implement `dyn/impl Trait` yet
475 return true; 512 return true;
476 } 513 }
477 let env = TraitEnvironment::lower(db, resolver);
478 let goal = generic_implements_goal(db, env, trait_, ty.clone()); 514 let goal = generic_implements_goal(db, env, trait_, ty.clone());
479 let solution = db.trait_solve(krate.into(), goal); 515 let solution = db.trait_solve(krate.into(), goal);
480 516
diff --git a/crates/ra_hir_ty/src/traits.rs b/crates/ra_hir_ty/src/traits.rs
index c4dc857bc..4aabd66dc 100644
--- a/crates/ra_hir_ty/src/traits.rs
+++ b/crates/ra_hir_ty/src/traits.rs
@@ -1,10 +1,12 @@
1//! Trait solving using Chalk. 1//! Trait solving using Chalk.
2use std::sync::{Arc, Mutex}; 2use std::{
3 panic,
4 sync::{Arc, Mutex},
5};
3 6
4use chalk_ir::cast::Cast; 7use chalk_ir::cast::Cast;
5use hir_def::{expr::ExprId, DefWithBodyId, ImplId, TraitId, TypeAliasId}; 8use hir_def::{expr::ExprId, DefWithBodyId, ImplId, TraitId, TypeAliasId};
6use log::debug; 9use ra_db::{impl_intern_key, salsa, Canceled, CrateId};
7use ra_db::{impl_intern_key, salsa, CrateId};
8use ra_prof::profile; 10use ra_prof::profile;
9use rustc_hash::FxHashSet; 11use rustc_hash::FxHashSet;
10 12
@@ -39,7 +41,7 @@ impl TraitSolver {
39 goal: &chalk_ir::UCanonical<chalk_ir::InEnvironment<chalk_ir::Goal<TypeFamily>>>, 41 goal: &chalk_ir::UCanonical<chalk_ir::InEnvironment<chalk_ir::Goal<TypeFamily>>>,
40 ) -> Option<chalk_solve::Solution<TypeFamily>> { 42 ) -> Option<chalk_solve::Solution<TypeFamily>> {
41 let context = ChalkContext { db, krate: self.krate }; 43 let context = ChalkContext { db, krate: self.krate };
42 debug!("solve goal: {:?}", goal); 44 log::debug!("solve goal: {:?}", goal);
43 let mut solver = match self.inner.lock() { 45 let mut solver = match self.inner.lock() {
44 Ok(it) => it, 46 Ok(it) => it,
45 // Our cancellation works via unwinding, but, as chalk is not 47 // Our cancellation works via unwinding, but, as chalk is not
@@ -47,8 +49,28 @@ impl TraitSolver {
47 // Ideally, we should also make chalk panic-safe. 49 // Ideally, we should also make chalk panic-safe.
48 Err(_) => ra_db::Canceled::throw(), 50 Err(_) => ra_db::Canceled::throw(),
49 }; 51 };
50 let solution = solver.solve(&context, goal); 52
51 debug!("solve({:?}) => {:?}", goal, solution); 53 let solution = panic::catch_unwind({
54 let solver = panic::AssertUnwindSafe(&mut solver);
55 let context = panic::AssertUnwindSafe(&context);
56 move || solver.0.solve(context.0, goal)
57 });
58
59 let solution = match solution {
60 Ok(it) => it,
61 Err(err) => {
62 if err.downcast_ref::<Canceled>().is_some() {
63 panic::resume_unwind(err)
64 } else {
65 log::error!("chalk panicked :-(");
66 // Reset the solver, as it is not panic-safe.
67 *solver = create_chalk_solver();
68 None
69 }
70 }
71 };
72
73 log::debug!("solve({:?}) => {:?}", goal, solution);
52 solution 74 solution
53 } 75 }
54} 76}
@@ -70,9 +92,13 @@ pub(crate) fn trait_solver_query(
70) -> TraitSolver { 92) -> TraitSolver {
71 db.salsa_runtime().report_untracked_read(); 93 db.salsa_runtime().report_untracked_read();
72 // krate parameter is just so we cache a unique solver per crate 94 // krate parameter is just so we cache a unique solver per crate
95 log::debug!("Creating new solver for crate {:?}", krate);
96 TraitSolver { krate, inner: Arc::new(Mutex::new(create_chalk_solver())) }
97}
98
99fn create_chalk_solver() -> chalk_solve::Solver<TypeFamily> {
73 let solver_choice = chalk_solve::SolverChoice::SLG { max_size: CHALK_SOLVER_MAX_SIZE }; 100 let solver_choice = chalk_solve::SolverChoice::SLG { max_size: CHALK_SOLVER_MAX_SIZE };
74 debug!("Creating new solver for crate {:?}", krate); 101 solver_choice.into_solver()
75 TraitSolver { krate, inner: Arc::new(Mutex::new(solver_choice.into_solver())) }
76} 102}
77 103
78/// Collects impls for the given trait in the whole dependency tree of `krate`. 104/// Collects impls for the given trait in the whole dependency tree of `krate`.
@@ -181,7 +207,7 @@ pub(crate) fn trait_solve_query(
181 goal: Canonical<InEnvironment<Obligation>>, 207 goal: Canonical<InEnvironment<Obligation>>,
182) -> Option<Solution> { 208) -> Option<Solution> {
183 let _p = profile("trait_solve_query"); 209 let _p = profile("trait_solve_query");
184 debug!("trait_solve_query({})", goal.value.value.display(db)); 210 log::debug!("trait_solve_query({})", goal.value.value.display(db));
185 211
186 if let Obligation::Projection(pred) = &goal.value.value { 212 if let Obligation::Projection(pred) = &goal.value.value {
187 if let Ty::Bound(_) = &pred.projection_ty.parameters[0] { 213 if let Ty::Bound(_) = &pred.projection_ty.parameters[0] {
diff --git a/crates/ra_ide/src/call_hierarchy.rs b/crates/ra_ide/src/call_hierarchy.rs
index 1cb712e32..aa5d60c7b 100644
--- a/crates/ra_ide/src/call_hierarchy.rs
+++ b/crates/ra_ide/src/call_hierarchy.rs
@@ -121,7 +121,7 @@ pub(crate) fn outgoing_calls(db: &RootDatabase, position: FilePosition) -> Optio
121 Some(macro_def.to_nav(db)) 121 Some(macro_def.to_nav(db))
122 } 122 }
123 } { 123 } {
124 Some((func_target.clone(), name_ref.value.text_range())) 124 Some((func_target, name_ref.value.text_range()))
125 } else { 125 } else {
126 None 126 None
127 } 127 }
diff --git a/crates/ra_ide/src/call_info.rs b/crates/ra_ide/src/call_info.rs
index a7023529b..72a68522e 100644
--- a/crates/ra_ide/src/call_info.rs
+++ b/crates/ra_ide/src/call_info.rs
@@ -1,10 +1,10 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2
3use hir::db::AstDatabase; 2use hir::db::AstDatabase;
4use ra_syntax::{ 3use ra_syntax::{
5 ast::{self, ArgListOwner}, 4 ast::{self, ArgListOwner},
6 match_ast, AstNode, SyntaxNode, 5 match_ast, AstNode, SyntaxNode,
7}; 6};
7
8use test_utils::tested_by; 8use test_utils::tested_by;
9 9
10use crate::{ 10use crate::{
@@ -51,36 +51,39 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal
51 // If we have a calling expression let's find which argument we are on 51 // If we have a calling expression let's find which argument we are on
52 let num_params = call_info.parameters().len(); 52 let num_params = call_info.parameters().len();
53 53
54 if num_params == 1 { 54 match num_params {
55 if !has_self { 55 0 => (),
56 call_info.active_parameter = Some(0); 56 1 => {
57 } 57 if !has_self {
58 } else if num_params > 1 { 58 call_info.active_parameter = Some(0);
59 // Count how many parameters into the call we are.
60 if let Some(arg_list) = calling_node.arg_list() {
61 // Number of arguments specified at the call site
62 let num_args_at_callsite = arg_list.args().count();
63
64 let arg_list_range = arg_list.syntax().text_range();
65 if !arg_list_range.contains_inclusive(position.offset) {
66 tested_by!(call_info_bad_offset);
67 return None;
68 } 59 }
60 }
61 _ => {
62 if let Some(arg_list) = calling_node.arg_list() {
63 // Number of arguments specified at the call site
64 let num_args_at_callsite = arg_list.args().count();
65
66 let arg_list_range = arg_list.syntax().text_range();
67 if !arg_list_range.contains_inclusive(position.offset) {
68 tested_by!(call_info_bad_offset);
69 return None;
70 }
69 71
70 let mut param = std::cmp::min( 72 let mut param = std::cmp::min(
71 num_args_at_callsite, 73 num_args_at_callsite,
72 arg_list 74 arg_list
73 .args() 75 .args()
74 .take_while(|arg| arg.syntax().text_range().end() < position.offset) 76 .take_while(|arg| arg.syntax().text_range().end() < position.offset)
75 .count(), 77 .count(),
76 ); 78 );
77 79
78 // If we are in a method account for `self` 80 // If we are in a method account for `self`
79 if has_self { 81 if has_self {
80 param += 1; 82 param += 1;
81 } 83 }
82 84
83 call_info.active_parameter = Some(param); 85 call_info.active_parameter = Some(param);
86 }
84 } 87 }
85 } 88 }
86 89
diff --git a/crates/ra_ide/src/completion/complete_dot.rs b/crates/ra_ide/src/completion/complete_dot.rs
index 210a685e4..2ca78c927 100644
--- a/crates/ra_ide/src/completion/complete_dot.rs
+++ b/crates/ra_ide/src/completion/complete_dot.rs
@@ -27,7 +27,7 @@ pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) {
27 complete_methods(acc, ctx, &receiver_ty); 27 complete_methods(acc, ctx, &receiver_ty);
28 28
29 // Suggest .await syntax for types that implement Future trait 29 // Suggest .await syntax for types that implement Future trait
30 if ctx.analyzer.impls_future(ctx.db, receiver_ty) { 30 if receiver_ty.impls_future(ctx.db) {
31 CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), "await") 31 CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), "await")
32 .detail("expr.await") 32 .detail("expr.await")
33 .insert_text("await") 33 .insert_text("await")
@@ -53,13 +53,16 @@ fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: &Ty
53} 53}
54 54
55fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: &Type) { 55fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: &Type) {
56 let mut seen_methods = FxHashSet::default(); 56 if let Some(krate) = ctx.module.map(|it| it.krate()) {
57 ctx.analyzer.iterate_method_candidates(ctx.db, receiver, None, |_ty, func| { 57 let mut seen_methods = FxHashSet::default();
58 if func.has_self_param(ctx.db) && seen_methods.insert(func.name(ctx.db)) { 58 let traits_in_scope = ctx.analyzer.traits_in_scope(ctx.db);
59 acc.add_function(ctx, func); 59 receiver.iterate_method_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, func| {
60 } 60 if func.has_self_param(ctx.db) && seen_methods.insert(func.name(ctx.db)) {
61 None::<()> 61 acc.add_function(ctx, func);
62 }); 62 }
63 None::<()>
64 });
65 }
63} 66}
64 67
65#[cfg(test)] 68#[cfg(test)]
@@ -525,6 +528,7 @@ mod tests {
525 528
526 //- /std/lib.rs 529 //- /std/lib.rs
527 pub mod future { 530 pub mod future {
531 #[lang = "future_trait"]
528 pub trait Future {} 532 pub trait Future {}
529 } 533 }
530 "###, CompletionKind::Keyword), 534 "###, CompletionKind::Keyword),
diff --git a/crates/ra_ide/src/completion/complete_path.rs b/crates/ra_ide/src/completion/complete_path.rs
index cc1f7c830..af24e9f48 100644
--- a/crates/ra_ide/src/completion/complete_path.rs
+++ b/crates/ra_ide/src/completion/complete_path.rs
@@ -26,7 +26,7 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
26 } 26 }
27 if let ScopeDef::Unknown = def { 27 if let ScopeDef::Unknown = def {
28 if let Some(name_ref) = ctx.name_ref_syntax.as_ref() { 28 if let Some(name_ref) = ctx.name_ref_syntax.as_ref() {
29 if &name_ref.syntax().text() == name.to_string().as_str() { 29 if name_ref.syntax().text() == name.to_string().as_str() {
30 // for `use self::foo<|>`, don't suggest `foo` as a completion 30 // for `use self::foo<|>`, don't suggest `foo` as a completion
31 tested_by!(dont_complete_current_use); 31 tested_by!(dont_complete_current_use);
32 continue; 32 continue;
@@ -49,22 +49,24 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
49 hir::ModuleDef::TypeAlias(a) => a.ty(ctx.db), 49 hir::ModuleDef::TypeAlias(a) => a.ty(ctx.db),
50 _ => unreachable!(), 50 _ => unreachable!(),
51 }; 51 };
52 ctx.analyzer.iterate_path_candidates(ctx.db, &ty, None, |_ty, item| {
53 match item {
54 hir::AssocItem::Function(func) => {
55 if !func.has_self_param(ctx.db) {
56 acc.add_function(ctx, func);
57 }
58 }
59 hir::AssocItem::Const(ct) => acc.add_const(ctx, ct),
60 hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
61 }
62 None::<()>
63 });
64 // Iterate assoc types separately 52 // Iterate assoc types separately
65 // FIXME: complete T::AssocType 53 // FIXME: complete T::AssocType
66 let krate = ctx.module.map(|m| m.krate()); 54 let krate = ctx.module.map(|m| m.krate());
67 if let Some(krate) = krate { 55 if let Some(krate) = krate {
56 let traits_in_scope = ctx.analyzer.traits_in_scope(ctx.db);
57 ty.iterate_path_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, item| {
58 match item {
59 hir::AssocItem::Function(func) => {
60 if !func.has_self_param(ctx.db) {
61 acc.add_function(ctx, func);
62 }
63 }
64 hir::AssocItem::Const(ct) => acc.add_const(ctx, ct),
65 hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
66 }
67 None::<()>
68 });
69
68 ty.iterate_impl_items(ctx.db, krate, |item| { 70 ty.iterate_impl_items(ctx.db, krate, |item| {
69 match item { 71 match item {
70 hir::AssocItem::Function(_) | hir::AssocItem::Const(_) => {} 72 hir::AssocItem::Function(_) | hir::AssocItem::Const(_) => {}
diff --git a/crates/ra_ide/src/extend_selection.rs b/crates/ra_ide/src/extend_selection.rs
index 70b6fde82..930e0c4c2 100644
--- a/crates/ra_ide/src/extend_selection.rs
+++ b/crates/ra_ide/src/extend_selection.rs
@@ -339,7 +339,7 @@ mod tests {
339 let (cursor, before) = extract_offset(before); 339 let (cursor, before) = extract_offset(before);
340 let (analysis, file_id) = single_file(&before); 340 let (analysis, file_id) = single_file(&before);
341 let range = TextRange::offset_len(cursor, 0.into()); 341 let range = TextRange::offset_len(cursor, 0.into());
342 let mut frange = FileRange { file_id: file_id, range }; 342 let mut frange = FileRange { file_id, range };
343 343
344 for &after in afters { 344 for &after in afters {
345 frange.range = analysis.extend_selection(frange).unwrap(); 345 frange.range = analysis.extend_selection(frange).unwrap();
diff --git a/crates/ra_ide/src/references.rs b/crates/ra_ide/src/references.rs
index 4e52e0e7b..2c753dade 100644
--- a/crates/ra_ide/src/references.rs
+++ b/crates/ra_ide/src/references.rs
@@ -166,7 +166,7 @@ pub(crate) fn find_all_refs(
166 Some(RangeInfo::new(range, ReferenceSearchResult { declaration, references })) 166 Some(RangeInfo::new(range, ReferenceSearchResult { declaration, references }))
167} 167}
168 168
169fn find_name<'a>( 169fn find_name(
170 db: &RootDatabase, 170 db: &RootDatabase,
171 syntax: &SyntaxNode, 171 syntax: &SyntaxNode,
172 position: FilePosition, 172 position: FilePosition,
@@ -253,13 +253,10 @@ fn decl_access(
253 let stmt = find_node_at_offset::<ast::LetStmt>(syntax, range.start())?; 253 let stmt = find_node_at_offset::<ast::LetStmt>(syntax, range.start())?;
254 if let Some(_) = stmt.initializer() { 254 if let Some(_) = stmt.initializer() {
255 let pat = stmt.pat()?; 255 let pat = stmt.pat()?;
256 match pat { 256 if let ast::Pat::BindPat(it) = pat {
257 ast::Pat::BindPat(it) => { 257 if it.name()?.text().as_str() == name {
258 if it.name()?.text().as_str() == name { 258 return Some(ReferenceAccess::Write);
259 return Some(ReferenceAccess::Write);
260 }
261 } 259 }
262 _ => {}
263 } 260 }
264 } 261 }
265 262
@@ -286,7 +283,7 @@ fn reference_access(kind: &NameKind, name_ref: &ast::NameRef) -> Option<Referenc
286 } 283 }
287 } 284 }
288 } 285 }
289 return Some(ReferenceAccess::Read); 286 Some(ReferenceAccess::Read)
290 }, 287 },
291 _ => {None} 288 _ => {None}
292 } 289 }
diff --git a/crates/ra_ide/src/references/search_scope.rs b/crates/ra_ide/src/references/search_scope.rs
index 241dd358f..f8211a746 100644
--- a/crates/ra_ide/src/references/search_scope.rs
+++ b/crates/ra_ide/src/references/search_scope.rs
@@ -82,8 +82,7 @@ impl NameDefinition {
82 return SearchScope::new(res); 82 return SearchScope::new(res);
83 } 83 }
84 84
85 let vis = 85 let vis = self.visibility.as_ref().map(|v| v.syntax().to_string()).unwrap_or_default();
86 self.visibility.as_ref().map(|v| v.syntax().to_string()).unwrap_or("".to_string());
87 86
88 if vis.as_str() == "pub(super)" { 87 if vis.as_str() == "pub(super)" {
89 if let Some(parent_module) = self.container.parent(db) { 88 if let Some(parent_module) = self.container.parent(db) {
diff --git a/crates/ra_lsp_server/src/main.rs b/crates/ra_lsp_server/src/main.rs
index cdd925c9f..3879eeff2 100644
--- a/crates/ra_lsp_server/src/main.rs
+++ b/crates/ra_lsp_server/src/main.rs
@@ -47,6 +47,10 @@ fn run_server() -> Result<()> {
47 let initialize_params = connection.initialize(server_capabilities)?; 47 let initialize_params = connection.initialize(server_capabilities)?;
48 let initialize_params: lsp_types::InitializeParams = serde_json::from_value(initialize_params)?; 48 let initialize_params: lsp_types::InitializeParams = serde_json::from_value(initialize_params)?;
49 49
50 if let Some(client_info) = initialize_params.client_info {
51 log::info!("Client '{}' {}", client_info.name, client_info.version.unwrap_or_default());
52 }
53
50 let cwd = std::env::current_dir()?; 54 let cwd = std::env::current_dir()?;
51 let root = initialize_params.root_uri.and_then(|it| it.to_file_path().ok()).unwrap_or(cwd); 55 let root = initialize_params.root_uri.and_then(|it| it.to_file_path().ok()).unwrap_or(cwd);
52 56
diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs
index 7a49cad86..84012b99d 100644
--- a/crates/ra_lsp_server/src/main_loop.rs
+++ b/crates/ra_lsp_server/src/main_loop.rs
@@ -417,6 +417,7 @@ fn loop_turn(
417 let msg = format!("workspace loaded, {} rust packages", n_packages); 417 let msg = format!("workspace loaded, {} rust packages", n_packages);
418 show_message(req::MessageType::Info, msg, &connection.sender); 418 show_message(req::MessageType::Info, msg, &connection.sender);
419 } 419 }
420 world_state.check_watcher.update();
420 } 421 }
421 422
422 if state_changed { 423 if state_changed {
diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs
index a592f0a12..d5a8bbe4d 100644
--- a/crates/ra_lsp_server/src/main_loop/handlers.rs
+++ b/crates/ra_lsp_server/src/main_loop/handlers.rs
@@ -710,6 +710,7 @@ pub fn handle_code_action(
710 title: command.title.clone(), 710 title: command.title.clone(),
711 kind: match assist.id { 711 kind: match assist.id {
712 AssistId("introduce_variable") => Some("refactor.extract.variable".to_string()), 712 AssistId("introduce_variable") => Some("refactor.extract.variable".to_string()),
713 AssistId("add_custom_impl") => Some("refactor.rewrite.add_custom_impl".to_string()),
713 _ => None, 714 _ => None,
714 }, 715 },
715 diagnostics: None, 716 diagnostics: None,
diff --git a/crates/ra_syntax/src/ast/expr_extensions.rs b/crates/ra_syntax/src/ast/expr_extensions.rs
index 3dfecfe76..6da4b1309 100644
--- a/crates/ra_syntax/src/ast/expr_extensions.rs
+++ b/crates/ra_syntax/src/ast/expr_extensions.rs
@@ -127,8 +127,8 @@ pub enum BinOp {
127} 127}
128 128
129impl BinOp { 129impl BinOp {
130 pub fn is_assignment(&self) -> bool { 130 pub fn is_assignment(self) -> bool {
131 match *self { 131 match self {
132 BinOp::Assignment 132 BinOp::Assignment
133 | BinOp::AddAssign 133 | BinOp::AddAssign
134 | BinOp::DivAssign 134 | BinOp::DivAssign
diff --git a/crates/ra_syntax/src/validation.rs b/crates/ra_syntax/src/validation.rs
index 222ac15f8..445e3b3e4 100644
--- a/crates/ra_syntax/src/validation.rs
+++ b/crates/ra_syntax/src/validation.rs
@@ -111,55 +111,46 @@ pub(crate) fn validate(root: &SyntaxNode) -> Vec<SyntaxError> {
111 errors 111 errors
112} 112}
113 113
114// FIXME: kill duplication
115fn validate_literal(literal: ast::Literal, acc: &mut Vec<SyntaxError>) { 114fn validate_literal(literal: ast::Literal, acc: &mut Vec<SyntaxError>) {
115 fn unquote(text: &str, prefix_len: usize, end_delimiter: char) -> Option<&str> {
116 text.rfind(end_delimiter).and_then(|end| text.get(prefix_len..end))
117 }
118
116 let token = literal.token(); 119 let token = literal.token();
117 let text = token.text().as_str(); 120 let text = token.text().as_str();
121
122 let mut push_err = |prefix_len, (off, err): (usize, unescape::EscapeError)| {
123 let off = token.text_range().start() + TextUnit::from_usize(off + prefix_len);
124 acc.push(SyntaxError::new(err.into(), off));
125 };
126
118 match token.kind() { 127 match token.kind() {
119 BYTE => { 128 BYTE => {
120 if let Some(end) = text.rfind('\'') { 129 if let Some(Err(e)) = unquote(text, 2, '\'').map(unescape::unescape_byte) {
121 if let Some(without_quotes) = text.get(2..end) { 130 push_err(2, e);
122 if let Err((off, err)) = unescape::unescape_byte(without_quotes) {
123 let off = token.text_range().start() + TextUnit::from_usize(off + 2);
124 acc.push(SyntaxError::new(err.into(), off))
125 }
126 }
127 } 131 }
128 } 132 }
129 CHAR => { 133 CHAR => {
130 if let Some(end) = text.rfind('\'') { 134 if let Some(Err(e)) = unquote(text, 1, '\'').map(unescape::unescape_char) {
131 if let Some(without_quotes) = text.get(1..end) { 135 push_err(1, e);
132 if let Err((off, err)) = unescape::unescape_char(without_quotes) {
133 let off = token.text_range().start() + TextUnit::from_usize(off + 1);
134 acc.push(SyntaxError::new(err.into(), off))
135 }
136 }
137 } 136 }
138 } 137 }
139 BYTE_STRING => { 138 BYTE_STRING => {
140 if let Some(end) = text.rfind('\"') { 139 if let Some(without_quotes) = unquote(text, 2, '"') {
141 if let Some(without_quotes) = text.get(2..end) { 140 unescape::unescape_byte_str(without_quotes, &mut |range, char| {
142 unescape::unescape_byte_str(without_quotes, &mut |range, char| { 141 if let Err(err) = char {
143 if let Err(err) = char { 142 push_err(2, (range.start, err));
144 let off = range.start; 143 }
145 let off = token.text_range().start() + TextUnit::from_usize(off + 2); 144 })
146 acc.push(SyntaxError::new(err.into(), off))
147 }
148 })
149 }
150 } 145 }
151 } 146 }
152 STRING => { 147 STRING => {
153 if let Some(end) = text.rfind('\"') { 148 if let Some(without_quotes) = unquote(text, 1, '"') {
154 if let Some(without_quotes) = text.get(1..end) { 149 unescape::unescape_str(without_quotes, &mut |range, char| {
155 unescape::unescape_str(without_quotes, &mut |range, char| { 150 if let Err(err) = char {
156 if let Err(err) = char { 151 push_err(1, (range.start, err));
157 let off = range.start; 152 }
158 let off = token.text_range().start() + TextUnit::from_usize(off + 1); 153 })
159 acc.push(SyntaxError::new(err.into(), off))
160 }
161 })
162 }
163 } 154 }
164 } 155 }
165 _ => (), 156 _ => (),