aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock10
-rw-r--r--crates/ra_assists/src/merge_match_arms.rs2
-rw-r--r--crates/ra_cli/src/main.rs2
-rw-r--r--crates/ra_hir/src/adt.rs11
-rw-r--r--crates/ra_hir/src/code_model.rs22
-rw-r--r--crates/ra_hir/src/db.rs6
-rw-r--r--crates/ra_hir/src/from_source.rs8
-rw-r--r--crates/ra_hir/src/nameres/collector.rs2
-rw-r--r--crates/ra_hir/src/nameres/raw.rs5
-rw-r--r--crates/ra_hir/src/source_binder.rs2
-rw-r--r--crates/ra_hir/src/ty.rs25
-rw-r--r--crates/ra_hir/src/ty/infer.rs67
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs9
-rw-r--r--crates/ra_hir/src/ty/tests.rs165
-rw-r--r--crates/ra_hir/src/ty/traits.rs44
-rw-r--r--crates/ra_hir/src/ty/traits/chalk.rs143
-rw-r--r--crates/ra_ide_api/src/completion/completion_context.rs2
-rw-r--r--crates/ra_ide_api/src/completion/presentation.rs2
-rw-r--r--crates/ra_ide_api/src/diagnostics.rs2
-rw-r--r--crates/ra_ide_api/src/display/navigation_target.rs4
-rw-r--r--crates/ra_mbe/src/subtree_source.rs10
-rw-r--r--crates/ra_parser/src/syntax_kind/generated.rs5
-rw-r--r--crates/ra_syntax/src/grammar.ron5
-rw-r--r--crates/ra_tools/src/boilerplate_gen.rs44
-rw-r--r--docs/user/README.md3
25 files changed, 449 insertions, 151 deletions
diff --git a/Cargo.lock b/Cargo.lock
index b6604dcc2..74570a978 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -122,7 +122,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
122[[package]] 122[[package]]
123name = "chalk-engine" 123name = "chalk-engine"
124version = "0.9.0" 124version = "0.9.0"
125source = "git+https://github.com/rust-lang/chalk.git#aa0c0582e4de1c0b84f99c412d92b9ca7ff06ddb" 125source = "git+https://github.com/rust-lang/chalk.git#df09cc603c0cff9ed95e5554055d483fdd756fbc"
126dependencies = [ 126dependencies = [
127 "chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git)", 127 "chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git)",
128 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 128 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -132,7 +132,7 @@ dependencies = [
132[[package]] 132[[package]]
133name = "chalk-ir" 133name = "chalk-ir"
134version = "0.1.0" 134version = "0.1.0"
135source = "git+https://github.com/rust-lang/chalk.git#aa0c0582e4de1c0b84f99c412d92b9ca7ff06ddb" 135source = "git+https://github.com/rust-lang/chalk.git#df09cc603c0cff9ed95e5554055d483fdd756fbc"
136dependencies = [ 136dependencies = [
137 "chalk-engine 0.9.0 (git+https://github.com/rust-lang/chalk.git)", 137 "chalk-engine 0.9.0 (git+https://github.com/rust-lang/chalk.git)",
138 "chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git)", 138 "chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git)",
@@ -142,7 +142,7 @@ dependencies = [
142[[package]] 142[[package]]
143name = "chalk-macros" 143name = "chalk-macros"
144version = "0.1.1" 144version = "0.1.1"
145source = "git+https://github.com/rust-lang/chalk.git#aa0c0582e4de1c0b84f99c412d92b9ca7ff06ddb" 145source = "git+https://github.com/rust-lang/chalk.git#df09cc603c0cff9ed95e5554055d483fdd756fbc"
146dependencies = [ 146dependencies = [
147 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 147 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
148] 148]
@@ -150,7 +150,7 @@ dependencies = [
150[[package]] 150[[package]]
151name = "chalk-rust-ir" 151name = "chalk-rust-ir"
152version = "0.1.0" 152version = "0.1.0"
153source = "git+https://github.com/rust-lang/chalk.git#aa0c0582e4de1c0b84f99c412d92b9ca7ff06ddb" 153source = "git+https://github.com/rust-lang/chalk.git#df09cc603c0cff9ed95e5554055d483fdd756fbc"
154dependencies = [ 154dependencies = [
155 "chalk-engine 0.9.0 (git+https://github.com/rust-lang/chalk.git)", 155 "chalk-engine 0.9.0 (git+https://github.com/rust-lang/chalk.git)",
156 "chalk-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git)", 156 "chalk-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git)",
@@ -160,7 +160,7 @@ dependencies = [
160[[package]] 160[[package]]
161name = "chalk-solve" 161name = "chalk-solve"
162version = "0.1.0" 162version = "0.1.0"
163source = "git+https://github.com/rust-lang/chalk.git#aa0c0582e4de1c0b84f99c412d92b9ca7ff06ddb" 163source = "git+https://github.com/rust-lang/chalk.git#df09cc603c0cff9ed95e5554055d483fdd756fbc"
164dependencies = [ 164dependencies = [
165 "chalk-engine 0.9.0 (git+https://github.com/rust-lang/chalk.git)", 165 "chalk-engine 0.9.0 (git+https://github.com/rust-lang/chalk.git)",
166 "chalk-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git)", 166 "chalk-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git)",
diff --git a/crates/ra_assists/src/merge_match_arms.rs b/crates/ra_assists/src/merge_match_arms.rs
index 225a48d3a..3b6a99895 100644
--- a/crates/ra_assists/src/merge_match_arms.rs
+++ b/crates/ra_assists/src/merge_match_arms.rs
@@ -8,7 +8,7 @@ pub(crate) fn merge_match_arms(mut ctx: AssistCtx<impl HirDatabase>) -> Option<A
8 // We check if the following match arm matches this one. We could, but don't, 8 // We check if the following match arm matches this one. We could, but don't,
9 // compare to the previous match arm as well. 9 // compare to the previous match arm as well.
10 let next = current_arm.syntax().next_sibling(); 10 let next = current_arm.syntax().next_sibling();
11 let next_arm = MatchArm::cast(next?.clone())?; 11 let next_arm = MatchArm::cast(next?)?;
12 12
13 // Don't try to handle arms with guards for now - can add support for this later 13 // Don't try to handle arms with guards for now - can add support for this later
14 if current_arm.guard().is_some() || next_arm.guard().is_some() { 14 if current_arm.guard().is_some() || next_arm.guard().is_some() {
diff --git a/crates/ra_cli/src/main.rs b/crates/ra_cli/src/main.rs
index 7aacf515d..8b91ba3e9 100644
--- a/crates/ra_cli/src/main.rs
+++ b/crates/ra_cli/src/main.rs
@@ -93,7 +93,7 @@ fn main() -> Result<()> {
93 (true, true) => Err("Invalid flags: -q conflicts with -v")?, 93 (true, true) => Err("Invalid flags: -q conflicts with -v")?,
94 }; 94 };
95 let memory_usage = matches.contains("--memory-usage"); 95 let memory_usage = matches.contains("--memory-usage");
96 let only = matches.value_from_str(["-o", "--only"])?.map(|v: String| v.to_owned()); 96 let only: Option<String> = matches.value_from_str(["-o", "--only"])?;
97 let path = { 97 let path = {
98 let mut trailing = matches.free()?; 98 let mut trailing = matches.free()?;
99 if trailing.len() != 1 { 99 if trailing.len() != 1 {
diff --git a/crates/ra_hir/src/adt.rs b/crates/ra_hir/src/adt.rs
index 56f2b7aa3..fbb4ff4d8 100644
--- a/crates/ra_hir/src/adt.rs
+++ b/crates/ra_hir/src/adt.rs
@@ -56,8 +56,7 @@ impl EnumVariant {
56 .zip(db.enum_data(self.parent).variants.iter()) 56 .zip(db.enum_data(self.parent).variants.iter())
57 .find(|(_syntax, (id, _))| *id == self.id) 57 .find(|(_syntax, (id, _))| *id == self.id)
58 .unwrap() 58 .unwrap()
59 .0 59 .0;
60 .to_owned();
61 Source { file_id: src.file_id, ast } 60 Source { file_id: src.file_id, ast }
62 } 61 }
63 pub(crate) fn variant_data(self, db: &impl DefDatabase) -> Arc<VariantData> { 62 pub(crate) fn variant_data(self, db: &impl DefDatabase) -> Arc<VariantData> {
@@ -203,12 +202,8 @@ impl StructField {
203 }; 202 };
204 203
205 let field_sources = match struct_kind { 204 let field_sources = match struct_kind {
206 ast::StructKind::Tuple(fl) => { 205 ast::StructKind::Tuple(fl) => fl.fields().map(|it| FieldSource::Pos(it)).collect(),
207 fl.fields().map(|it| FieldSource::Pos(it.to_owned())).collect() 206 ast::StructKind::Named(fl) => fl.fields().map(|it| FieldSource::Named(it)).collect(),
208 }
209 ast::StructKind::Named(fl) => {
210 fl.fields().map(|it| FieldSource::Named(it.to_owned())).collect()
211 }
212 ast::StructKind::Unit => Vec::new(), 207 ast::StructKind::Unit => Vec::new(),
213 }; 208 };
214 let ast = field_sources 209 let ast = field_sources
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index 12399c6ac..9fecba63d 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -161,7 +161,7 @@ impl ModuleSource {
161 ) -> ModuleSource { 161 ) -> ModuleSource {
162 match (file_id, decl_id) { 162 match (file_id, decl_id) {
163 (Some(file_id), _) => { 163 (Some(file_id), _) => {
164 let source_file = db.parse(file_id).tree().to_owned(); 164 let source_file = db.parse(file_id).tree();
165 ModuleSource::SourceFile(source_file) 165 ModuleSource::SourceFile(source_file)
166 } 166 }
167 (None, Some(item_id)) => { 167 (None, Some(item_id)) => {
@@ -551,6 +551,14 @@ impl DefWithBody {
551 DefWithBody::Static(s) => s.resolver(db), 551 DefWithBody::Static(s) => s.resolver(db),
552 } 552 }
553 } 553 }
554
555 pub(crate) fn krate(self, db: &impl HirDatabase) -> Option<Crate> {
556 match self {
557 DefWithBody::Const(c) => c.krate(db),
558 DefWithBody::Function(f) => f.krate(db),
559 DefWithBody::Static(s) => s.krate(db),
560 }
561 }
554} 562}
555 563
556pub trait HasBody: Copy { 564pub trait HasBody: Copy {
@@ -671,6 +679,10 @@ impl Function {
671 self.id.module(db) 679 self.id.module(db)
672 } 680 }
673 681
682 pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> {
683 self.module(db).krate(db)
684 }
685
674 pub fn name(self, db: &impl HirDatabase) -> Name { 686 pub fn name(self, db: &impl HirDatabase) -> Name {
675 self.data(db).name.clone() 687 self.data(db).name.clone()
676 } 688 }
@@ -745,6 +757,10 @@ impl Const {
745 self.id.module(db) 757 self.id.module(db)
746 } 758 }
747 759
760 pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> {
761 self.module(db).krate(db)
762 }
763
748 pub fn data(self, db: &impl HirDatabase) -> Arc<ConstData> { 764 pub fn data(self, db: &impl HirDatabase) -> Arc<ConstData> {
749 db.const_data(self) 765 db.const_data(self)
750 } 766 }
@@ -824,6 +840,10 @@ impl Static {
824 self.id.module(db) 840 self.id.module(db)
825 } 841 }
826 842
843 pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> {
844 self.module(db).krate(db)
845 }
846
827 pub fn data(self, db: &impl HirDatabase) -> Arc<ConstData> { 847 pub fn data(self, db: &impl HirDatabase) -> Arc<ConstData> {
828 db.static_data(self) 848 db.static_data(self)
829 } 849 }
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index 05259dcbb..2b20ae02b 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -13,8 +13,8 @@ use crate::{
13 nameres::{CrateDefMap, ImportSourceMap, Namespace, RawItems}, 13 nameres::{CrateDefMap, ImportSourceMap, Namespace, RawItems},
14 traits::TraitData, 14 traits::TraitData,
15 ty::{ 15 ty::{
16 method_resolution::CrateImplBlocks, CallableDef, FnSig, GenericPredicate, InferenceResult, 16 method_resolution::CrateImplBlocks, traits::Impl, CallableDef, FnSig, GenericPredicate,
17 Substs, Ty, TypableDef, TypeCtor, 17 InferenceResult, Substs, Ty, TypableDef, TypeCtor,
18 }, 18 },
19 type_alias::TypeAliasData, 19 type_alias::TypeAliasData,
20 AstIdMap, Const, ConstData, Crate, DefWithBody, Enum, ErasedFileAstId, ExprScopes, FnData, 20 AstIdMap, Const, ConstData, Crate, DefWithBody, Enum, ErasedFileAstId, ExprScopes, FnData,
@@ -50,7 +50,7 @@ pub trait InternDatabase: SourceDatabase {
50 #[salsa::interned] 50 #[salsa::interned]
51 fn intern_type_ctor(&self, type_ctor: TypeCtor) -> ids::TypeCtorId; 51 fn intern_type_ctor(&self, type_ctor: TypeCtor) -> ids::TypeCtorId;
52 #[salsa::interned] 52 #[salsa::interned]
53 fn intern_impl_block(&self, impl_block: ImplBlock) -> ids::GlobalImplId; 53 fn intern_impl(&self, impl_: Impl) -> ids::GlobalImplId;
54} 54}
55 55
56/// This database has access to source code, so queries here are not really 56/// This database has access to source code, so queries here are not really
diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs
index f3194595f..7b6d9b240 100644
--- a/crates/ra_hir/src/from_source.rs
+++ b/crates/ra_hir/src/from_source.rs
@@ -137,7 +137,7 @@ impl ModuleSource {
137 match &find_node_at_offset::<ast::Module>(parse.tree().syntax(), position.offset) { 137 match &find_node_at_offset::<ast::Module>(parse.tree().syntax(), position.offset) {
138 Some(m) if !m.has_semi() => ModuleSource::Module(m.clone()), 138 Some(m) if !m.has_semi() => ModuleSource::Module(m.clone()),
139 _ => { 139 _ => {
140 let source_file = parse.tree().to_owned(); 140 let source_file = parse.tree();
141 ModuleSource::SourceFile(source_file) 141 ModuleSource::SourceFile(source_file)
142 } 142 }
143 } 143 }
@@ -149,15 +149,15 @@ impl ModuleSource {
149 child: &SyntaxNode, 149 child: &SyntaxNode,
150 ) -> ModuleSource { 150 ) -> ModuleSource {
151 if let Some(m) = child.ancestors().filter_map(ast::Module::cast).find(|it| !it.has_semi()) { 151 if let Some(m) = child.ancestors().filter_map(ast::Module::cast).find(|it| !it.has_semi()) {
152 ModuleSource::Module(m.clone()) 152 ModuleSource::Module(m)
153 } else { 153 } else {
154 let source_file = db.parse(file_id).tree().to_owned(); 154 let source_file = db.parse(file_id).tree();
155 ModuleSource::SourceFile(source_file) 155 ModuleSource::SourceFile(source_file)
156 } 156 }
157 } 157 }
158 158
159 pub fn from_file_id(db: &(impl DefDatabase + AstDatabase), file_id: FileId) -> ModuleSource { 159 pub fn from_file_id(db: &(impl DefDatabase + AstDatabase), file_id: FileId) -> ModuleSource {
160 let source_file = db.parse(file_id).tree().to_owned(); 160 let source_file = db.parse(file_id).tree();
161 ModuleSource::SourceFile(source_file) 161 ModuleSource::SourceFile(source_file)
162 } 162 }
163} 163}
diff --git a/crates/ra_hir/src/nameres/collector.rs b/crates/ra_hir/src/nameres/collector.rs
index 6b253ac40..ef7dc6ebe 100644
--- a/crates/ra_hir/src/nameres/collector.rs
+++ b/crates/ra_hir/src/nameres/collector.rs
@@ -166,7 +166,7 @@ where
166 // In Rust, `#[macro_export]` macros are unconditionally visible at the 166 // In Rust, `#[macro_export]` macros are unconditionally visible at the
167 // crate root, even if the parent modules is **not** visible. 167 // crate root, even if the parent modules is **not** visible.
168 if export { 168 if export {
169 self.update(self.def_map.root, None, &[(name.clone(), Resolution::from_macro(macro_))]); 169 self.update(self.def_map.root, None, &[(name, Resolution::from_macro(macro_))]);
170 } 170 }
171 } 171 }
172 172
diff --git a/crates/ra_hir/src/nameres/raw.rs b/crates/ra_hir/src/nameres/raw.rs
index 8bf883ac2..29aaddbf1 100644
--- a/crates/ra_hir/src/nameres/raw.rs
+++ b/crates/ra_hir/src/nameres/raw.rs
@@ -36,10 +36,7 @@ type ImportSource = Either<ast::UseTree, ast::ExternCrateItem>;
36 36
37impl ImportSourcePtr { 37impl ImportSourcePtr {
38 fn to_node(self, file: &SourceFile) -> ImportSource { 38 fn to_node(self, file: &SourceFile) -> ImportSource {
39 self.map( 39 self.map(|ptr| ptr.to_node(file.syntax()), |ptr| ptr.to_node(file.syntax()))
40 |ptr| ptr.to_node(file.syntax()).to_owned(),
41 |ptr| ptr.to_node(file.syntax()).to_owned(),
42 )
43 } 40 }
44} 41}
45 42
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index 296acc364..bd4be8430 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -73,7 +73,7 @@ fn def_with_body_from_child_node(
73 if let Some(def) = ast::ConstDef::cast(node.clone()) { 73 if let Some(def) = ast::ConstDef::cast(node.clone()) {
74 return Some(Const { id: ctx.to_def(&def) }.into()); 74 return Some(Const { id: ctx.to_def(&def) }.into());
75 } 75 }
76 if let Some(def) = ast::StaticDef::cast(node.clone()) { 76 if let Some(def) = ast::StaticDef::cast(node) {
77 return Some(Static { id: ctx.to_def(&def) }.into()); 77 return Some(Static { id: ctx.to_def(&def) }.into());
78 } 78 }
79 None 79 None
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index 36bfb10ce..fae9c1e22 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -16,7 +16,10 @@ use std::ops::Deref;
16use std::sync::Arc; 16use std::sync::Arc;
17use std::{fmt, mem}; 17use std::{fmt, mem};
18 18
19use crate::{db::HirDatabase, type_ref::Mutability, Adt, GenericParams, Name, Trait, TypeAlias}; 19use crate::{
20 db::HirDatabase, expr::ExprId, type_ref::Mutability, Adt, DefWithBody, GenericParams, Name,
21 Trait, TypeAlias,
22};
20use display::{HirDisplay, HirFormatter}; 23use display::{HirDisplay, HirFormatter};
21 24
22pub(crate) use autoderef::autoderef; 25pub(crate) use autoderef::autoderef;
@@ -100,6 +103,12 @@ pub enum TypeCtor {
100 /// couldn't find a better representation. In that case, we generate 103 /// couldn't find a better representation. In that case, we generate
101 /// an **application type** like `(Iterator::Item)<T>`. 104 /// an **application type** like `(Iterator::Item)<T>`.
102 AssociatedType(TypeAlias), 105 AssociatedType(TypeAlias),
106
107 /// The type of a specific closure.
108 ///
109 /// The closure signature is stored in a `FnPtr` type in the first type
110 /// parameter.
111 Closure { def: DefWithBody, expr: ExprId },
103} 112}
104 113
105/// A nominal type with (maybe 0) type parameters. This might be a primitive 114/// A nominal type with (maybe 0) type parameters. This might be a primitive
@@ -214,7 +223,7 @@ impl Substs {
214 } 223 }
215 224
216 pub fn prefix(&self, n: usize) -> Substs { 225 pub fn prefix(&self, n: usize) -> Substs {
217 Substs(self.0.iter().cloned().take(n).collect::<Vec<_>>().into()) 226 Substs(self.0[..std::cmp::min(self.0.len(), n)].into())
218 } 227 }
219 228
220 pub fn walk(&self, f: &mut impl FnMut(&Ty)) { 229 pub fn walk(&self, f: &mut impl FnMut(&Ty)) {
@@ -481,6 +490,10 @@ impl Ty {
481 let sig = db.callable_item_signature(def); 490 let sig = db.callable_item_signature(def);
482 Some(sig.subst(&a_ty.parameters)) 491 Some(sig.subst(&a_ty.parameters))
483 } 492 }
493 TypeCtor::Closure { .. } => {
494 let sig_param = &a_ty.parameters[0];
495 sig_param.callable_sig(db)
496 }
484 _ => None, 497 _ => None,
485 }, 498 },
486 _ => None, 499 _ => None,
@@ -720,6 +733,14 @@ impl HirDisplay for ApplicationTy {
720 write!(f, ">")?; 733 write!(f, ">")?;
721 } 734 }
722 } 735 }
736 TypeCtor::Closure { .. } => {
737 let sig = self.parameters[0]
738 .callable_sig(f.db)
739 .expect("first closure parameter should contain signature");
740 write!(f, "|")?;
741 f.write_joined(sig.params(), ", ")?;
742 write!(f, "| -> {}", sig.ret().display(f.db))?;
743 }
723 } 744 }
724 Ok(()) 745 Ok(())
725 } 746 }
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index 81a8623bf..76b4b6faa 100644
--- a/crates/ra_hir/src/ty/infer.rs
+++ b/crates/ra_hir/src/ty/infer.rs
@@ -436,7 +436,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
436 436
437 fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty { 437 fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty {
438 let var = self.new_type_var(); 438 let var = self.new_type_var();
439 let predicate = ProjectionPredicate { projection_ty: proj_ty.clone(), ty: var.clone() }; 439 let predicate = ProjectionPredicate { projection_ty: proj_ty, ty: var.clone() };
440 let obligation = Obligation::Projection(predicate); 440 let obligation = Obligation::Projection(predicate);
441 self.obligations.push(obligation); 441 self.obligations.push(obligation);
442 var 442 var
@@ -790,11 +790,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
790 }; 790 };
791 self.unify(&expected_receiver_ty, &actual_receiver_ty); 791 self.unify(&expected_receiver_ty, &actual_receiver_ty);
792 792
793 let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown)); 793 self.check_call_arguments(args, &param_tys);
794 for (arg, param_ty) in args.iter().zip(param_iter) {
795 let param_ty = self.normalize_associated_types_in(param_ty);
796 self.infer_expr(*arg, &Expectation::has_type(param_ty));
797 }
798 let ret_ty = self.normalize_associated_types_in(ret_ty); 794 let ret_ty = self.normalize_associated_types_in(ret_ty);
799 ret_ty 795 ret_ty
800 } 796 }
@@ -885,18 +881,37 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
885 Expr::Lambda { body, args, arg_types } => { 881 Expr::Lambda { body, args, arg_types } => {
886 assert_eq!(args.len(), arg_types.len()); 882 assert_eq!(args.len(), arg_types.len());
887 883
884 let mut sig_tys = Vec::new();
885
888 for (arg_pat, arg_type) in args.iter().zip(arg_types.iter()) { 886 for (arg_pat, arg_type) in args.iter().zip(arg_types.iter()) {
889 let expected = if let Some(type_ref) = arg_type { 887 let expected = if let Some(type_ref) = arg_type {
890 self.make_ty(type_ref) 888 self.make_ty(type_ref)
891 } else { 889 } else {
892 Ty::Unknown 890 Ty::Unknown
893 }; 891 };
894 self.infer_pat(*arg_pat, &expected, BindingMode::default()); 892 let arg_ty = self.infer_pat(*arg_pat, &expected, BindingMode::default());
893 sig_tys.push(arg_ty);
895 } 894 }
896 895
897 // FIXME: infer lambda type etc. 896 // add return type
898 let _body_ty = self.infer_expr(*body, &Expectation::none()); 897 let ret_ty = self.new_type_var();
899 Ty::Unknown 898 sig_tys.push(ret_ty.clone());
899 let sig_ty = Ty::apply(
900 TypeCtor::FnPtr { num_args: sig_tys.len() as u16 - 1 },
901 sig_tys.into(),
902 );
903 let closure_ty = Ty::apply_one(
904 TypeCtor::Closure { def: self.body.owner(), expr: tgt_expr },
905 sig_ty,
906 );
907
908 // Eagerly try to relate the closure type with the expected
909 // type, otherwise we often won't have enough information to
910 // infer the body.
911 self.coerce(&closure_ty, &expected.ty);
912
913 self.infer_expr(*body, &Expectation::has_type(ret_ty));
914 closure_ty
900 } 915 }
901 Expr::Call { callee, args } => { 916 Expr::Call { callee, args } => {
902 let callee_ty = self.infer_expr(*callee, &Expectation::none()); 917 let callee_ty = self.infer_expr(*callee, &Expectation::none());
@@ -909,11 +924,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
909 } 924 }
910 }; 925 };
911 self.register_obligations_for_call(&callee_ty); 926 self.register_obligations_for_call(&callee_ty);
912 let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown)); 927 self.check_call_arguments(args, &param_tys);
913 for (arg, param_ty) in args.iter().zip(param_iter) {
914 let param_ty = self.normalize_associated_types_in(param_ty);
915 self.infer_expr(*arg, &Expectation::has_type(param_ty));
916 }
917 let ret_ty = self.normalize_associated_types_in(ret_ty); 928 let ret_ty = self.normalize_associated_types_in(ret_ty);
918 ret_ty 929 ret_ty
919 } 930 }
@@ -942,7 +953,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
942 arm_tys.push(self.infer_expr_inner(arm.expr, &expected)); 953 arm_tys.push(self.infer_expr_inner(arm.expr, &expected));
943 } 954 }
944 955
945 let lub_ty = calculate_least_upper_bound(expected.ty.clone(), &arm_tys); 956 let lub_ty = calculate_least_upper_bound(expected.ty, &arm_tys);
946 957
947 for arm_ty in &arm_tys { 958 for arm_ty in &arm_tys {
948 self.coerce(arm_ty, &lub_ty); 959 self.coerce(arm_ty, &lub_ty);
@@ -1255,6 +1266,30 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1255 ty 1266 ty
1256 } 1267 }
1257 1268
1269 fn check_call_arguments(&mut self, args: &[ExprId], param_tys: &[Ty]) {
1270 // Quoting https://github.com/rust-lang/rust/blob/6ef275e6c3cb1384ec78128eceeb4963ff788dca/src/librustc_typeck/check/mod.rs#L3325 --
1271 // We do this in a pretty awful way: first we type-check any arguments
1272 // that are not closures, then we type-check the closures. This is so
1273 // that we have more information about the types of arguments when we
1274 // type-check the functions. This isn't really the right way to do this.
1275 for &check_closures in &[false, true] {
1276 let param_iter = param_tys.iter().cloned().chain(repeat(Ty::Unknown));
1277 for (&arg, param_ty) in args.iter().zip(param_iter) {
1278 let is_closure = match &self.body[arg] {
1279 Expr::Lambda { .. } => true,
1280 _ => false,
1281 };
1282
1283 if is_closure != check_closures {
1284 continue;
1285 }
1286
1287 let param_ty = self.normalize_associated_types_in(param_ty);
1288 self.infer_expr(arg, &Expectation::has_type(param_ty));
1289 }
1290 }
1291 }
1292
1258 fn collect_const(&mut self, data: &ConstData) { 1293 fn collect_const(&mut self, data: &ConstData) {
1259 self.return_ty = self.make_ty(data.type_ref()); 1294 self.return_ty = self.make_ty(data.type_ref());
1260 } 1295 }
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs
index 8b46b11a9..4b71b376f 100644
--- a/crates/ra_hir/src/ty/method_resolution.rs
+++ b/crates/ra_hir/src/ty/method_resolution.rs
@@ -16,6 +16,7 @@ use crate::{
16 resolve::Resolver, 16 resolve::Resolver,
17 ty::primitive::{FloatBitness, UncertainFloatTy, UncertainIntTy}, 17 ty::primitive::{FloatBitness, UncertainFloatTy, UncertainIntTy},
18 ty::{Ty, TypeCtor}, 18 ty::{Ty, TypeCtor},
19 type_ref::Mutability,
19 AssocItem, Crate, Function, Module, Name, Trait, 20 AssocItem, Crate, Function, Module, Name, Trait,
20}; 21};
21 22
@@ -130,7 +131,7 @@ fn def_crates(db: &impl HirDatabase, cur_crate: Crate, ty: &Ty) -> Option<ArrayV
130 ($db:expr, $cur_crate:expr, $($name:expr),+ $(,)?) => {{ 131 ($db:expr, $cur_crate:expr, $($name:expr),+ $(,)?) => {{
131 let mut v = ArrayVec::<[Crate; 2]>::new(); 132 let mut v = ArrayVec::<[Crate; 2]>::new();
132 $( 133 $(
133 v.push($db.lang_item($cur_crate, $name.into())?.krate($db)?); 134 v.extend($db.lang_item($cur_crate, $name.into()).and_then(|item| item.krate($db)));
134 )+ 135 )+
135 Some(v) 136 Some(v)
136 }}; 137 }};
@@ -149,8 +150,10 @@ fn def_crates(db: &impl HirDatabase, cur_crate: Crate, ty: &Ty) -> Option<ArrayV
149 TypeCtor::Int(UncertainIntTy::Known(i)) => { 150 TypeCtor::Int(UncertainIntTy::Known(i)) => {
150 lang_item_crate!(db, cur_crate, i.ty_to_string()) 151 lang_item_crate!(db, cur_crate, i.ty_to_string())
151 } 152 }
152 TypeCtor::Str => lang_item_crate!(db, cur_crate, "str"), 153 TypeCtor::Str => lang_item_crate!(db, cur_crate, "str_alloc", "str"),
153 TypeCtor::Slice => lang_item_crate!(db, cur_crate, "slice_alloc", "slice"), 154 TypeCtor::Slice => lang_item_crate!(db, cur_crate, "slice_alloc", "slice"),
155 TypeCtor::RawPtr(Mutability::Shared) => lang_item_crate!(db, cur_crate, "const_ptr"),
156 TypeCtor::RawPtr(Mutability::Mut) => lang_item_crate!(db, cur_crate, "mut_ptr"),
154 _ => None, 157 _ => None,
155 }, 158 },
156 _ => None, 159 _ => None,
@@ -290,7 +293,7 @@ pub(crate) fn implements_trait(
290 return true; 293 return true;
291 } 294 }
292 let env = lower::trait_env(db, resolver); 295 let env = lower::trait_env(db, resolver);
293 let goal = generic_implements_goal(db, env.clone(), trait_, ty.clone()); 296 let goal = generic_implements_goal(db, env, trait_, ty.clone());
294 let solution = db.trait_solve(krate, goal); 297 let solution = db.trait_solve(krate, goal);
295 298
296 solution.is_some() 299 solution.is_some()
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index 3ac1fbdd5..2872cd27b 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -1077,7 +1077,6 @@ fn test(x: &i32) {
1077} 1077}
1078"#), 1078"#),
1079 @r###" 1079 @r###"
1080
1081 [9; 10) 'x': &i32 1080 [9; 10) 'x': &i32
1082 [18; 369) '{ ...o_x; }': () 1081 [18; 369) '{ ...o_x; }': ()
1083 [28; 29) 'y': &i32 1082 [28; 29) 'y': &i32
@@ -1107,8 +1106,8 @@ fn test(x: &i32) {
1107 [177; 205) '{ ... }': () 1106 [177; 205) '{ ... }': ()
1108 [191; 192) 'h': {unknown} 1107 [191; 192) 'h': {unknown}
1109 [195; 198) 'val': {unknown} 1108 [195; 198) 'val': {unknown}
1110 [215; 221) 'lambda': {unknown} 1109 [215; 221) 'lambda': |u64, u64, i32| -> i32
1111 [224; 256) '|a: u6...b; c }': {unknown} 1110 [224; 256) '|a: u6...b; c }': |u64, u64, i32| -> i32
1112 [225; 226) 'a': u64 1111 [225; 226) 'a': u64
1113 [233; 234) 'b': u64 1112 [233; 234) 'b': u64
1114 [236; 237) 'c': i32 1113 [236; 237) 'c': i32
@@ -2836,12 +2835,11 @@ fn test() -> u64 {
2836} 2835}
2837"#), 2836"#),
2838 @r###" 2837 @r###"
2839
2840 [44; 102) '{ ...0(2) }': u64 2838 [44; 102) '{ ...0(2) }': u64
2841 [54; 55) 'a': S 2839 [54; 55) 'a': S
2842 [58; 59) 'S': S(fn(u32) -> u64) -> S 2840 [58; 59) 'S': S(fn(u32) -> u64) -> S
2843 [58; 68) 'S(|i| 2*i)': S 2841 [58; 68) 'S(|i| 2*i)': S
2844 [60; 67) '|i| 2*i': fn(u32) -> u64 2842 [60; 67) '|i| 2*i': |i32| -> i32
2845 [61; 62) 'i': i32 2843 [61; 62) 'i': i32
2846 [64; 65) '2': i32 2844 [64; 65) '2': i32
2847 [64; 67) '2*i': i32 2845 [64; 67) '2*i': i32
@@ -3802,13 +3800,13 @@ fn test<T: Trait<Type = u32>>(x: T, y: impl Trait<Type = i64>) {
3802 [296; 299) 'get': fn get<T>(T) -> <T as Trait>::Type 3800 [296; 299) 'get': fn get<T>(T) -> <T as Trait>::Type
3803 [296; 302) 'get(x)': {unknown} 3801 [296; 302) 'get(x)': {unknown}
3804 [300; 301) 'x': T 3802 [300; 301) 'x': T
3805 [308; 312) 'get2': fn get2<{unknown}, S<{unknown}>>(T) -> U 3803 [308; 312) 'get2': fn get2<{unknown}, T>(T) -> U
3806 [308; 315) 'get2(x)': {unknown} 3804 [308; 315) 'get2(x)': {unknown}
3807 [313; 314) 'x': T 3805 [313; 314) 'x': T
3808 [321; 324) 'get': fn get<impl Trait<Type = i64>>(T) -> <T as Trait>::Type 3806 [321; 324) 'get': fn get<impl Trait<Type = i64>>(T) -> <T as Trait>::Type
3809 [321; 327) 'get(y)': {unknown} 3807 [321; 327) 'get(y)': {unknown}
3810 [325; 326) 'y': impl Trait<Type = i64> 3808 [325; 326) 'y': impl Trait<Type = i64>
3811 [333; 337) 'get2': fn get2<{unknown}, S<{unknown}>>(T) -> U 3809 [333; 337) 'get2': fn get2<{unknown}, impl Trait<Type = i64>>(T) -> U
3812 [333; 340) 'get2(y)': {unknown} 3810 [333; 340) 'get2(y)': {unknown}
3813 [338; 339) 'y': impl Trait<Type = i64> 3811 [338; 339) 'y': impl Trait<Type = i64>
3814 [346; 349) 'get': fn get<S<u64>>(T) -> <T as Trait>::Type 3812 [346; 349) 'get': fn get<S<u64>>(T) -> <T as Trait>::Type
@@ -3992,49 +3990,50 @@ fn test<F: FnOnce(u32, u64) -> u128>(f: F) {
3992fn closure_1() { 3990fn closure_1() {
3993 assert_snapshot!( 3991 assert_snapshot!(
3994 infer(r#" 3992 infer(r#"
3993#[lang = "fn_once"]
3995trait FnOnce<Args> { 3994trait FnOnce<Args> {
3996 type Output; 3995 type Output;
3997} 3996}
3998 3997
3999enum Option<T> { Some(T), None } 3998enum Option<T> { Some(T), None }
4000impl<T> Option<T> { 3999impl<T> Option<T> {
4001 fn map<U, F: FnOnce(T) -> U>(self, f: F) -> U {} 4000 fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Option<U> {}
4002} 4001}
4003 4002
4004fn test() { 4003fn test() {
4005 let x = Option::Some(1i32); 4004 let x = Option::Some(1u32);
4006 x.map(|v| v + 1); 4005 x.map(|v| v + 1);
4007 x.map(|_v| 1u64); 4006 x.map(|_v| 1u64);
4008 let y: Option<i64> = x.map(|_v| 1); 4007 let y: Option<i64> = x.map(|_v| 1);
4009} 4008}
4010"#), 4009"#),
4011 @r###" 4010 @r###"
4012 [128; 132) 'self': Option<T> 4011 [148; 152) 'self': Option<T>
4013 [134; 135) 'f': F 4012 [154; 155) 'f': F
4014 [145; 147) '{}': () 4013 [173; 175) '{}': ()
4015 [161; 280) '{ ... 1); }': () 4014 [189; 308) '{ ... 1); }': ()
4016 [171; 172) 'x': Option<i32> 4015 [199; 200) 'x': Option<u32>
4017 [175; 187) 'Option::Some': Some<i32>(T) -> Option<T> 4016 [203; 215) 'Option::Some': Some<u32>(T) -> Option<T>
4018 [175; 193) 'Option...(1i32)': Option<i32> 4017 [203; 221) 'Option...(1u32)': Option<u32>
4019 [188; 192) '1i32': i32 4018 [216; 220) '1u32': u32
4020 [199; 200) 'x': Option<i32> 4019 [227; 228) 'x': Option<u32>
4021 [199; 215) 'x.map(...v + 1)': {unknown} 4020 [227; 243) 'x.map(...v + 1)': Option<u32>
4022 [205; 214) '|v| v + 1': {unknown} 4021 [233; 242) '|v| v + 1': |u32| -> u32
4023 [206; 207) 'v': {unknown} 4022 [234; 235) 'v': u32
4024 [209; 210) 'v': {unknown} 4023 [237; 238) 'v': u32
4025 [209; 214) 'v + 1': i32 4024 [237; 242) 'v + 1': u32
4026 [213; 214) '1': i32 4025 [241; 242) '1': u32
4027 [221; 222) 'x': Option<i32> 4026 [249; 250) 'x': Option<u32>
4028 [221; 237) 'x.map(... 1u64)': {unknown} 4027 [249; 265) 'x.map(... 1u64)': Option<u64>
4029 [227; 236) '|_v| 1u64': {unknown} 4028 [255; 264) '|_v| 1u64': |u32| -> u64
4030 [228; 230) '_v': {unknown} 4029 [256; 258) '_v': u32
4031 [232; 236) '1u64': u64 4030 [260; 264) '1u64': u64
4032 [247; 248) 'y': Option<i64> 4031 [275; 276) 'y': Option<i64>
4033 [264; 265) 'x': Option<i32> 4032 [292; 293) 'x': Option<u32>
4034 [264; 277) 'x.map(|_v| 1)': Option<i64> 4033 [292; 305) 'x.map(|_v| 1)': Option<i64>
4035 [270; 276) '|_v| 1': {unknown} 4034 [298; 304) '|_v| 1': |u32| -> i64
4036 [271; 273) '_v': {unknown} 4035 [299; 301) '_v': u32
4037 [275; 276) '1': i32 4036 [303; 304) '1': i64
4038 "### 4037 "###
4039 ); 4038 );
4040} 4039}
@@ -4060,17 +4059,17 @@ fn test<F: FnOnce(u32) -> u64>(f: F) {
4060 [85; 86) 'f': F 4059 [85; 86) 'f': F
4061 [85; 89) 'f(1)': {unknown} 4060 [85; 89) 'f(1)': {unknown}
4062 [87; 88) '1': i32 4061 [87; 88) '1': i32
4063 [99; 100) 'g': {unknown} 4062 [99; 100) 'g': |u64| -> i32
4064 [103; 112) '|v| v + 1': {unknown} 4063 [103; 112) '|v| v + 1': |u64| -> i32
4065 [104; 105) 'v': {unknown} 4064 [104; 105) 'v': u64
4066 [107; 108) 'v': {unknown} 4065 [107; 108) 'v': u64
4067 [107; 112) 'v + 1': i32 4066 [107; 112) 'v + 1': i32
4068 [111; 112) '1': i32 4067 [111; 112) '1': i32
4069 [118; 119) 'g': {unknown} 4068 [118; 119) 'g': |u64| -> i32
4070 [118; 125) 'g(1u64)': {unknown} 4069 [118; 125) 'g(1u64)': i32
4071 [120; 124) '1u64': u64 4070 [120; 124) '1u64': u64
4072 [135; 136) 'h': {unknown} 4071 [135; 136) 'h': |u128| -> u128
4073 [139; 152) '|v| 1u128 + v': {unknown} 4072 [139; 152) '|v| 1u128 + v': |u128| -> u128
4074 [140; 141) 'v': u128 4073 [140; 141) 'v': u128
4075 [143; 148) '1u128': u128 4074 [143; 148) '1u128': u128
4076 [143; 152) '1u128 + v': u128 4075 [143; 152) '1u128 + v': u128
@@ -4080,6 +4079,86 @@ fn test<F: FnOnce(u32) -> u64>(f: F) {
4080} 4079}
4081 4080
4082#[test] 4081#[test]
4082fn closure_as_argument_inference_order() {
4083 assert_snapshot!(
4084 infer(r#"
4085#[lang = "fn_once"]
4086trait FnOnce<Args> {
4087 type Output;
4088}
4089
4090fn foo1<T, U, F: FnOnce(T) -> U>(x: T, f: F) -> U {}
4091fn foo2<T, U, F: FnOnce(T) -> U>(f: F, x: T) -> U {}
4092
4093struct S;
4094impl S {
4095 fn method(self) -> u64;
4096
4097 fn foo1<T, U, F: FnOnce(T) -> U>(self, x: T, f: F) -> U {}
4098 fn foo2<T, U, F: FnOnce(T) -> U>(self, f: F, x: T) -> U {}
4099}
4100
4101fn test() {
4102 let x1 = foo1(S, |s| s.method());
4103 let x2 = foo2(|s| s.method(), S);
4104 let x3 = S.foo1(S, |s| s.method());
4105 let x4 = S.foo2(|s| s.method(), S);
4106}
4107"#),
4108 @r###"
4109 [95; 96) 'x': T
4110 [101; 102) 'f': F
4111 [112; 114) '{}': ()
4112 [148; 149) 'f': F
4113 [154; 155) 'x': T
4114 [165; 167) '{}': ()
4115 [202; 206) 'self': S
4116 [254; 258) 'self': S
4117 [260; 261) 'x': T
4118 [266; 267) 'f': F
4119 [277; 279) '{}': ()
4120 [317; 321) 'self': S
4121 [323; 324) 'f': F
4122 [329; 330) 'x': T
4123 [340; 342) '{}': ()
4124 [356; 515) '{ ... S); }': ()
4125 [366; 368) 'x1': u64
4126 [371; 375) 'foo1': fn foo1<S, u64, |S| -> u64>(T, F) -> U
4127 [371; 394) 'foo1(S...hod())': u64
4128 [376; 377) 'S': S
4129 [379; 393) '|s| s.method()': |S| -> u64
4130 [380; 381) 's': S
4131 [383; 384) 's': S
4132 [383; 393) 's.method()': u64
4133 [404; 406) 'x2': u64
4134 [409; 413) 'foo2': fn foo2<S, u64, |S| -> u64>(F, T) -> U
4135 [409; 432) 'foo2(|...(), S)': u64
4136 [414; 428) '|s| s.method()': |S| -> u64
4137 [415; 416) 's': S
4138 [418; 419) 's': S
4139 [418; 428) 's.method()': u64
4140 [430; 431) 'S': S
4141 [442; 444) 'x3': u64
4142 [447; 448) 'S': S
4143 [447; 472) 'S.foo1...hod())': u64
4144 [454; 455) 'S': S
4145 [457; 471) '|s| s.method()': |S| -> u64
4146 [458; 459) 's': S
4147 [461; 462) 's': S
4148 [461; 471) 's.method()': u64
4149 [482; 484) 'x4': u64
4150 [487; 488) 'S': S
4151 [487; 512) 'S.foo2...(), S)': u64
4152 [494; 508) '|s| s.method()': |S| -> u64
4153 [495; 496) 's': S
4154 [498; 499) 's': S
4155 [498; 508) 's.method()': u64
4156 [510; 511) 'S': S
4157 "###
4158 );
4159}
4160
4161#[test]
4083fn unselected_projection_in_trait_env_1() { 4162fn unselected_projection_in_trait_env_1() {
4084 let t = type_at( 4163 let t = type_at(
4085 r#" 4164 r#"
diff --git a/crates/ra_hir/src/ty/traits.rs b/crates/ra_hir/src/ty/traits.rs
index c0c132809..d11dab294 100644
--- a/crates/ra_hir/src/ty/traits.rs
+++ b/crates/ra_hir/src/ty/traits.rs
@@ -9,7 +9,7 @@ use ra_prof::profile;
9use rustc_hash::FxHashSet; 9use rustc_hash::FxHashSet;
10 10
11use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk}; 11use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk};
12use crate::{db::HirDatabase, Crate, ImplBlock, Trait}; 12use crate::{db::HirDatabase, expr::ExprId, Crate, DefWithBody, ImplBlock, Trait};
13 13
14use self::chalk::{from_chalk, ToChalk}; 14use self::chalk::{from_chalk, ToChalk};
15 15
@@ -173,6 +173,14 @@ pub(crate) fn trait_solve_query(
173) -> Option<Solution> { 173) -> Option<Solution> {
174 let _p = profile("trait_solve_query"); 174 let _p = profile("trait_solve_query");
175 debug!("trait_solve_query({})", goal.value.value.display(db)); 175 debug!("trait_solve_query({})", goal.value.value.display(db));
176
177 if let Obligation::Projection(pred) = &goal.value.value {
178 if let Ty::Bound(_) = &pred.projection_ty.parameters[0] {
179 // Hack: don't ask Chalk to normalize with an unknown self type, it'll say that's impossible
180 return Some(Solution::Ambig(Guidance::Unknown));
181 }
182 }
183
176 let canonical = goal.to_chalk(db).cast(); 184 let canonical = goal.to_chalk(db).cast();
177 // We currently don't deal with universes (I think / hope they're not yet 185 // We currently don't deal with universes (I think / hope they're not yet
178 // relevant for our use cases?) 186 // relevant for our use cases?)
@@ -252,3 +260,37 @@ pub enum Guidance {
252 /// There's no useful information to feed back to type inference 260 /// There's no useful information to feed back to type inference
253 Unknown, 261 Unknown,
254} 262}
263
264#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
265pub enum FnTrait {
266 FnOnce,
267 FnMut,
268 Fn,
269}
270
271impl FnTrait {
272 fn lang_item_name(self) -> &'static str {
273 match self {
274 FnTrait::FnOnce => "fn_once",
275 FnTrait::FnMut => "fn_mut",
276 FnTrait::Fn => "fn",
277 }
278 }
279}
280
281#[derive(Debug, Clone, PartialEq, Eq, Hash)]
282pub struct ClosureFnTraitImplData {
283 def: DefWithBody,
284 expr: ExprId,
285 fn_trait: FnTrait,
286}
287
288/// An impl. Usually this comes from an impl block, but some built-in types get
289/// synthetic impls.
290#[derive(Debug, Clone, PartialEq, Eq, Hash)]
291pub enum Impl {
292 /// A normal impl from an impl block.
293 ImplBlock(ImplBlock),
294 /// Closure types implement the Fn traits synthetically.
295 ClosureFnTraitImpl(ClosureFnTraitImplData),
296}
diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs
index 2e17c00e4..d83706f86 100644
--- a/crates/ra_hir/src/ty/traits/chalk.rs
+++ b/crates/ra_hir/src/ty/traits/chalk.rs
@@ -12,7 +12,7 @@ use chalk_rust_ir::{AssociatedTyDatum, ImplDatum, StructDatum, TraitDatum};
12use ra_db::salsa::{InternId, InternKey}; 12use ra_db::salsa::{InternId, InternKey};
13use test_utils::tested_by; 13use test_utils::tested_by;
14 14
15use super::{Canonical, ChalkContext, Obligation}; 15use super::{Canonical, ChalkContext, Impl, Obligation};
16use crate::{ 16use crate::{
17 db::HirDatabase, 17 db::HirDatabase,
18 generics::GenericDef, 18 generics::GenericDef,
@@ -111,7 +111,7 @@ impl ToChalk for Ty {
111 } 111 }
112 chalk_ir::Ty::ForAll(_) => unimplemented!(), 112 chalk_ir::Ty::ForAll(_) => unimplemented!(),
113 chalk_ir::Ty::BoundVar(idx) => Ty::Bound(idx as u32), 113 chalk_ir::Ty::BoundVar(idx) => Ty::Bound(idx as u32),
114 chalk_ir::Ty::InferenceVar(_iv) => panic!("unexpected chalk infer ty"), 114 chalk_ir::Ty::InferenceVar(_iv) => Ty::Unknown,
115 } 115 }
116 } 116 }
117} 117}
@@ -175,15 +175,15 @@ impl ToChalk for TypeCtor {
175 } 175 }
176} 176}
177 177
178impl ToChalk for ImplBlock { 178impl ToChalk for Impl {
179 type Chalk = chalk_ir::ImplId; 179 type Chalk = chalk_ir::ImplId;
180 180
181 fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::ImplId { 181 fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::ImplId {
182 db.intern_impl_block(self).into() 182 db.intern_impl(self).into()
183 } 183 }
184 184
185 fn from_chalk(db: &impl HirDatabase, impl_id: chalk_ir::ImplId) -> ImplBlock { 185 fn from_chalk(db: &impl HirDatabase, impl_id: chalk_ir::ImplId) -> Impl {
186 db.lookup_intern_impl_block(impl_id.into()) 186 db.lookup_intern_impl(impl_id.into())
187 } 187 }
188} 188}
189 189
@@ -385,18 +385,39 @@ where
385 fn impl_datum(&self, impl_id: ImplId) -> Arc<ImplDatum> { 385 fn impl_datum(&self, impl_id: ImplId) -> Arc<ImplDatum> {
386 self.db.impl_datum(self.krate, impl_id) 386 self.db.impl_datum(self.krate, impl_id)
387 } 387 }
388 fn impls_for_trait(&self, trait_id: chalk_ir::TraitId) -> Vec<ImplId> { 388 fn impls_for_trait(
389 &self,
390 trait_id: chalk_ir::TraitId,
391 parameters: &[Parameter],
392 ) -> Vec<ImplId> {
389 debug!("impls_for_trait {:?}", trait_id); 393 debug!("impls_for_trait {:?}", trait_id);
390 if trait_id == UNKNOWN_TRAIT { 394 if trait_id == UNKNOWN_TRAIT {
391 return Vec::new(); 395 return Vec::new();
392 } 396 }
393 let trait_: Trait = from_chalk(self.db, trait_id); 397 let trait_: Trait = from_chalk(self.db, trait_id);
394 let result: Vec<_> = self 398 let mut result: Vec<_> = self
395 .db 399 .db
396 .impls_for_trait(self.krate, trait_) 400 .impls_for_trait(self.krate, trait_)
397 .iter() 401 .iter()
398 .map(|impl_block| impl_block.to_chalk(self.db)) 402 .copied()
403 .map(Impl::ImplBlock)
404 .map(|impl_| impl_.to_chalk(self.db))
399 .collect(); 405 .collect();
406
407 let ty: Ty = from_chalk(self.db, parameters[0].assert_ty_ref().clone());
408 if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Closure { def, expr }, .. }) = ty {
409 for &fn_trait in
410 [super::FnTrait::FnOnce, super::FnTrait::FnMut, super::FnTrait::Fn].iter()
411 {
412 if let Some(actual_trait) = get_fn_trait(self.db, self.krate, fn_trait) {
413 if trait_ == actual_trait {
414 let impl_ = super::ClosureFnTraitImplData { def, expr, fn_trait };
415 result.push(Impl::ClosureFnTraitImpl(impl_).to_chalk(self.db));
416 }
417 }
418 }
419 }
420
400 debug!("impls_for_trait returned {} impls", result.len()); 421 debug!("impls_for_trait returned {} impls", result.len());
401 result 422 result
402 } 423 }
@@ -415,8 +436,7 @@ where
415 &self, 436 &self,
416 projection: &'p chalk_ir::ProjectionTy, 437 projection: &'p chalk_ir::ProjectionTy,
417 ) -> (Arc<AssociatedTyDatum>, &'p [Parameter], &'p [Parameter]) { 438 ) -> (Arc<AssociatedTyDatum>, &'p [Parameter], &'p [Parameter]) {
418 let proj_ty: ProjectionTy = from_chalk(self.db, projection.clone()); 439 debug!("split_projection {:?}", projection);
419 debug!("split_projection {:?} = {}", projection, proj_ty.display(self.db));
420 // we don't support GATs, so I think this should always be correct currently 440 // we don't support GATs, so I think this should always be correct currently
421 (self.db.associated_ty_data(projection.associated_ty_id), &projection.parameters, &[]) 441 (self.db.associated_ty_data(projection.associated_ty_id), &projection.parameters, &[])
422 } 442 }
@@ -568,6 +588,10 @@ pub(crate) fn struct_datum_query(
568 type_alias.krate(db) != Some(krate), 588 type_alias.krate(db) != Some(krate),
569 ) 589 )
570 } 590 }
591 TypeCtor::Closure { def, .. } => {
592 let upstream = def.krate(db) != Some(krate);
593 (1, vec![], upstream)
594 }
571 }; 595 };
572 let flags = chalk_rust_ir::StructFlags { 596 let flags = chalk_rust_ir::StructFlags {
573 upstream, 597 upstream,
@@ -595,7 +619,21 @@ pub(crate) fn impl_datum_query(
595) -> Arc<ImplDatum> { 619) -> Arc<ImplDatum> {
596 let _p = ra_prof::profile("impl_datum"); 620 let _p = ra_prof::profile("impl_datum");
597 debug!("impl_datum {:?}", impl_id); 621 debug!("impl_datum {:?}", impl_id);
598 let impl_block: ImplBlock = from_chalk(db, impl_id); 622 let impl_: Impl = from_chalk(db, impl_id);
623 match impl_ {
624 Impl::ImplBlock(impl_block) => impl_block_datum(db, krate, impl_id, impl_block),
625 Impl::ClosureFnTraitImpl(data) => {
626 closure_fn_trait_impl_datum(db, krate, impl_id, data).unwrap_or_else(invalid_impl_datum)
627 }
628 }
629}
630
631fn impl_block_datum(
632 db: &impl HirDatabase,
633 krate: Crate,
634 impl_id: ImplId,
635 impl_block: ImplBlock,
636) -> Arc<ImplDatum> {
599 let generic_params = impl_block.generic_params(db); 637 let generic_params = impl_block.generic_params(db);
600 let bound_vars = Substs::bound_vars(&generic_params); 638 let bound_vars = Substs::bound_vars(&generic_params);
601 let trait_ref = impl_block 639 let trait_ref = impl_block
@@ -654,6 +692,87 @@ pub(crate) fn impl_datum_query(
654 Arc::new(impl_datum) 692 Arc::new(impl_datum)
655} 693}
656 694
695fn invalid_impl_datum() -> Arc<ImplDatum> {
696 let trait_ref = chalk_ir::TraitRef {
697 trait_id: UNKNOWN_TRAIT,
698 parameters: vec![chalk_ir::Ty::BoundVar(0).cast()],
699 };
700 let impl_datum_bound = chalk_rust_ir::ImplDatumBound {
701 trait_ref: chalk_rust_ir::PolarizedTraitRef::Positive(trait_ref),
702 where_clauses: Vec::new(),
703 associated_ty_values: Vec::new(),
704 impl_type: chalk_rust_ir::ImplType::External,
705 };
706 let impl_datum = ImplDatum { binders: make_binders(impl_datum_bound, 1) };
707 Arc::new(impl_datum)
708}
709
710fn closure_fn_trait_impl_datum(
711 db: &impl HirDatabase,
712 krate: Crate,
713 impl_id: ImplId,
714 data: super::ClosureFnTraitImplData,
715) -> Option<Arc<ImplDatum>> {
716 // for some closure |X, Y| -> Z:
717 // impl<T, U, V> Fn<(T, U)> for closure<fn(T, U) -> V> { Output = V }
718
719 let fn_once_trait = get_fn_trait(db, krate, super::FnTrait::FnOnce)?;
720 let trait_ = get_fn_trait(db, krate, data.fn_trait)?; // get corresponding fn trait
721
722 let num_args: u16 = match &db.body_hir(data.def)[data.expr] {
723 crate::expr::Expr::Lambda { args, .. } => args.len() as u16,
724 _ => {
725 log::warn!("closure for closure type {:?} not found", data);
726 0
727 }
728 };
729
730 let arg_ty = Ty::apply(
731 TypeCtor::Tuple { cardinality: num_args },
732 (0..num_args).map(|i| Ty::Bound(i.into())).collect::<Vec<_>>().into(),
733 );
734 let output_ty = Ty::Bound(num_args.into());
735 let sig_ty = Ty::apply(
736 TypeCtor::FnPtr { num_args },
737 (0..num_args + 1).map(|i| Ty::Bound(i.into())).collect::<Vec<_>>().into(),
738 );
739
740 let self_ty = Ty::apply_one(TypeCtor::Closure { def: data.def, expr: data.expr }, sig_ty);
741
742 let trait_ref = TraitRef { trait_, substs: vec![self_ty, arg_ty].into() };
743
744 let output_ty_id = fn_once_trait.associated_type_by_name(db, &crate::name::OUTPUT_TYPE)?;
745
746 let output_ty_value = chalk_rust_ir::AssociatedTyValue {
747 associated_ty_id: output_ty_id.to_chalk(db),
748 impl_id,
749 value: make_binders(
750 chalk_rust_ir::AssociatedTyValueBound { ty: output_ty.to_chalk(db) },
751 0,
752 ),
753 };
754
755 let impl_type = chalk_rust_ir::ImplType::External;
756
757 let impl_datum_bound = chalk_rust_ir::ImplDatumBound {
758 trait_ref: chalk_rust_ir::PolarizedTraitRef::Positive(trait_ref.to_chalk(db)),
759 where_clauses: Vec::new(),
760 associated_ty_values: vec![output_ty_value],
761 impl_type,
762 };
763 let impl_datum = ImplDatum { binders: make_binders(impl_datum_bound, num_args as usize + 1) };
764 Some(Arc::new(impl_datum))
765}
766
767fn get_fn_trait(db: &impl HirDatabase, krate: Crate, fn_trait: super::FnTrait) -> Option<Trait> {
768 let lang_items = db.lang_items(krate);
769 let target = lang_items.target(fn_trait.lang_item_name())?;
770 match target {
771 crate::lang_item::LangItemTarget::Trait(t) => Some(*t),
772 _ => None,
773 }
774}
775
657fn id_from_chalk<T: InternKey>(chalk_id: chalk_ir::RawId) -> T { 776fn id_from_chalk<T: InternKey>(chalk_id: chalk_ir::RawId) -> T {
658 T::from_intern_id(InternId::from(chalk_id.index)) 777 T::from_intern_id(InternId::from(chalk_id.index))
659} 778}
diff --git a/crates/ra_ide_api/src/completion/completion_context.rs b/crates/ra_ide_api/src/completion/completion_context.rs
index 59bd3689b..57542152f 100644
--- a/crates/ra_ide_api/src/completion/completion_context.rs
+++ b/crates/ra_ide_api/src/completion/completion_context.rs
@@ -94,7 +94,7 @@ impl<'a> CompletionContext<'a> {
94 // actual completion. 94 // actual completion.
95 let file = { 95 let file = {
96 let edit = AtomTextEdit::insert(offset, "intellijRulezz".to_string()); 96 let edit = AtomTextEdit::insert(offset, "intellijRulezz".to_string());
97 original_parse.reparse(&edit).tree().to_owned() 97 original_parse.reparse(&edit).tree()
98 }; 98 };
99 99
100 // First, let's try to complete a reference to some declaration. 100 // First, let's try to complete a reference to some declaration.
diff --git a/crates/ra_ide_api/src/completion/presentation.rs b/crates/ra_ide_api/src/completion/presentation.rs
index ad414412b..b8aa433c1 100644
--- a/crates/ra_ide_api/src/completion/presentation.rs
+++ b/crates/ra_ide_api/src/completion/presentation.rs
@@ -76,7 +76,7 @@ impl Completions {
76 None, 76 None,
77 ), 77 ),
78 ScopeDef::MacroDef(mac) => { 78 ScopeDef::MacroDef(mac) => {
79 self.add_macro(ctx, Some(local_name.clone()), *mac); 79 self.add_macro(ctx, Some(local_name), *mac);
80 return; 80 return;
81 } 81 }
82 ScopeDef::Unknown => { 82 ScopeDef::Unknown => {
diff --git a/crates/ra_ide_api/src/diagnostics.rs b/crates/ra_ide_api/src/diagnostics.rs
index 1ae152e5b..93e1e7c2d 100644
--- a/crates/ra_ide_api/src/diagnostics.rs
+++ b/crates/ra_ide_api/src/diagnostics.rs
@@ -86,7 +86,7 @@ pub(crate) fn diagnostics(db: &RootDatabase, file_id: FileId) -> Vec<Diagnostic>
86 fix: Some(fix), 86 fix: Some(fix),
87 }) 87 })
88 }); 88 });
89 let source_file = db.parse(file_id).tree().to_owned(); 89 let source_file = db.parse(file_id).tree();
90 let src = 90 let src =
91 hir::Source { file_id: file_id.into(), ast: hir::ModuleSource::SourceFile(source_file) }; 91 hir::Source { file_id: file_id.into(), ast: hir::ModuleSource::SourceFile(source_file) };
92 if let Some(m) = hir::Module::from_definition(db, src) { 92 if let Some(m) = hir::Module::from_definition(db, src) {
diff --git a/crates/ra_ide_api/src/display/navigation_target.rs b/crates/ra_ide_api/src/display/navigation_target.rs
index 11f73ccfd..d3e774bd0 100644
--- a/crates/ra_ide_api/src/display/navigation_target.rs
+++ b/crates/ra_ide_api/src/display/navigation_target.rs
@@ -304,7 +304,7 @@ impl NavigationTarget {
304 304
305pub(crate) fn docs_from_symbol(db: &RootDatabase, symbol: &FileSymbol) -> Option<String> { 305pub(crate) fn docs_from_symbol(db: &RootDatabase, symbol: &FileSymbol) -> Option<String> {
306 let parse = db.parse(symbol.file_id); 306 let parse = db.parse(symbol.file_id);
307 let node = symbol.ptr.to_node(parse.tree().syntax()).to_owned(); 307 let node = symbol.ptr.to_node(parse.tree().syntax());
308 308
309 visitor() 309 visitor()
310 .visit(|it: ast::FnDef| it.doc_comment_text()) 310 .visit(|it: ast::FnDef| it.doc_comment_text())
@@ -326,7 +326,7 @@ pub(crate) fn docs_from_symbol(db: &RootDatabase, symbol: &FileSymbol) -> Option
326/// e.g. `struct Name`, `enum Name`, `fn Name` 326/// e.g. `struct Name`, `enum Name`, `fn Name`
327pub(crate) fn description_from_symbol(db: &RootDatabase, symbol: &FileSymbol) -> Option<String> { 327pub(crate) fn description_from_symbol(db: &RootDatabase, symbol: &FileSymbol) -> Option<String> {
328 let parse = db.parse(symbol.file_id); 328 let parse = db.parse(symbol.file_id);
329 let node = symbol.ptr.to_node(parse.tree().syntax()).to_owned(); 329 let node = symbol.ptr.to_node(parse.tree().syntax());
330 330
331 visitor() 331 visitor()
332 .visit(|node: ast::FnDef| node.short_label()) 332 .visit(|node: ast::FnDef| node.short_label())
diff --git a/crates/ra_mbe/src/subtree_source.rs b/crates/ra_mbe/src/subtree_source.rs
index 9d6d0133f..cf7458905 100644
--- a/crates/ra_mbe/src/subtree_source.rs
+++ b/crates/ra_mbe/src/subtree_source.rs
@@ -148,15 +148,7 @@ fn convert_ident(ident: &tt::Ident) -> TtToken {
148} 148}
149 149
150fn convert_punct(p: tt::Punct) -> TtToken { 150fn convert_punct(p: tt::Punct) -> TtToken {
151 let kind = match p.char { 151 let kind = SyntaxKind::from_char(p.char).unwrap();
152 // lexer may produce compound tokens for these ones
153 '.' => T![.],
154 ':' => T![:],
155 '=' => T![=],
156 '!' => T![!],
157 '-' => T![-],
158 c => SyntaxKind::from_char(c).unwrap(),
159 };
160 let text = { 152 let text = {
161 let mut buf = [0u8; 4]; 153 let mut buf = [0u8; 4];
162 let s: &str = p.char.encode_utf8(&mut buf); 154 let s: &str = p.char.encode_utf8(&mut buf);
diff --git a/crates/ra_parser/src/syntax_kind/generated.rs b/crates/ra_parser/src/syntax_kind/generated.rs
index 23eb3c9cb..8b43d93fe 100644
--- a/crates/ra_parser/src/syntax_kind/generated.rs
+++ b/crates/ra_parser/src/syntax_kind/generated.rs
@@ -342,6 +342,11 @@ impl SyntaxKind {
342 '^' => CARET, 342 '^' => CARET,
343 '%' => PERCENT, 343 '%' => PERCENT,
344 '_' => UNDERSCORE, 344 '_' => UNDERSCORE,
345 '.' => DOT,
346 ':' => COLON,
347 '=' => EQ,
348 '!' => EXCL,
349 '-' => MINUS,
345 _ => return None, 350 _ => return None,
346 }; 351 };
347 Some(tok) 352 Some(tok)
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron
index da9de2214..5f395501a 100644
--- a/crates/ra_syntax/src/grammar.ron
+++ b/crates/ra_syntax/src/grammar.ron
@@ -1,7 +1,7 @@
1// Stores definitions which must be used in multiple places 1// Stores definitions which must be used in multiple places
2// See `cargo gen-syntax` (defined in crates/tools/src/main.rs) 2// See `cargo gen-syntax` (defined in crates/tools/src/main.rs)
3Grammar( 3Grammar(
4 single_byte_tokens: [ 4 punct: [
5 (";", "SEMI"), 5 (";", "SEMI"),
6 (",", "COMMA"), 6 (",", "COMMA"),
7 ("(", "L_PAREN"), 7 ("(", "L_PAREN"),
@@ -25,9 +25,6 @@ Grammar(
25 ("^", "CARET"), 25 ("^", "CARET"),
26 ("%", "PERCENT"), 26 ("%", "PERCENT"),
27 ("_", "UNDERSCORE"), 27 ("_", "UNDERSCORE"),
28 ],
29 // Tokens for which the longest match must be chosen (e.g. `..` is a DOTDOT, but `.` is a DOT)
30 multi_byte_tokens: [
31 (".", "DOT"), 28 (".", "DOT"),
32 ("..", "DOTDOT"), 29 ("..", "DOTDOT"),
33 ("...", "DOTDOTDOT"), 30 ("...", "DOTDOTDOT"),
diff --git a/crates/ra_tools/src/boilerplate_gen.rs b/crates/ra_tools/src/boilerplate_gen.rs
index 578f13a3e..1d112c0af 100644
--- a/crates/ra_tools/src/boilerplate_gen.rs
+++ b/crates/ra_tools/src/boilerplate_gen.rs
@@ -160,31 +160,24 @@ fn generate_ast(grammar: &Grammar) -> Result<String> {
160} 160}
161 161
162fn generate_syntax_kinds(grammar: &Grammar) -> Result<String> { 162fn generate_syntax_kinds(grammar: &Grammar) -> Result<String> {
163 let single_byte_tokens_values = 163 let (single_byte_tokens_values, single_byte_tokens): (Vec<_>, Vec<_>) = grammar
164 grammar.single_byte_tokens.iter().map(|(token, _name)| token.chars().next().unwrap()); 164 .punct
165 let single_byte_tokens = grammar
166 .single_byte_tokens
167 .iter() 165 .iter()
168 .map(|(_token, name)| format_ident!("{}", name)) 166 .filter(|(token, _name)| token.len() == 1)
169 .collect::<Vec<_>>(); 167 .map(|(token, name)| (token.chars().next().unwrap(), format_ident!("{}", name)))
170 168 .unzip();
171 let punctuation_values = 169
172 grammar.single_byte_tokens.iter().chain(grammar.multi_byte_tokens.iter()).map( 170 let punctuation_values = grammar.punct.iter().map(|(token, _name)| {
173 |(token, _name)| { 171 if "{}[]()".contains(token) {
174 if "{}[]()".contains(token) { 172 let c = token.chars().next().unwrap();
175 let c = token.chars().next().unwrap(); 173 quote! { #c }
176 quote! { #c } 174 } else {
177 } else { 175 let cs = token.chars().map(|c| Punct::new(c, Spacing::Joint));
178 let cs = token.chars().map(|c| Punct::new(c, Spacing::Joint)); 176 quote! { #(#cs)* }
179 quote! { #(#cs)* } 177 }
180 } 178 });
181 }, 179 let punctuation =
182 ); 180 grammar.punct.iter().map(|(_token, name)| format_ident!("{}", name)).collect::<Vec<_>>();
183 let punctuation = single_byte_tokens
184 .clone()
185 .into_iter()
186 .chain(grammar.multi_byte_tokens.iter().map(|(_token, name)| format_ident!("{}", name)))
187 .collect::<Vec<_>>();
188 181
189 let full_keywords_values = &grammar.keywords; 182 let full_keywords_values = &grammar.keywords;
190 let full_keywords = 183 let full_keywords =
@@ -294,8 +287,7 @@ fn reformat(text: impl std::fmt::Display) -> Result<String> {
294 287
295#[derive(Deserialize, Debug)] 288#[derive(Deserialize, Debug)]
296struct Grammar { 289struct Grammar {
297 single_byte_tokens: Vec<(String, String)>, 290 punct: Vec<(String, String)>,
298 multi_byte_tokens: Vec<(String, String)>,
299 keywords: Vec<String>, 291 keywords: Vec<String>,
300 contextual_keywords: Vec<String>, 292 contextual_keywords: Vec<String>,
301 literals: Vec<String>, 293 literals: Vec<String>,
diff --git a/docs/user/README.md b/docs/user/README.md
index 6d92359e2..9d03cad1c 100644
--- a/docs/user/README.md
+++ b/docs/user/README.md
@@ -76,7 +76,8 @@ See [microsoft/vscode#72308](https://github.com/microsoft/vscode/issues/72308) f
76 This is not very intuitive and a limitation of a current implementation. 76 This is not very intuitive and a limitation of a current implementation.
77* `rust-analyzer.useClientWatching`: use client provided file watching instead 77* `rust-analyzer.useClientWatching`: use client provided file watching instead
78 of notify watching. 78 of notify watching.
79* `rust-analyzer.cargo-watch.check-arguments`: cargo-watch check arguments. 79* `rust-analyzer.cargo-watch.command`: `cargo-watch` command. (e.g: `clippy` will run as `cargo watch -x clippy` )
80* `rust-analyzer.cargo-watch.arguments`: cargo-watch check arguments.
80 (e.g: `--features="shumway,pdf"` will run as `cargo watch -x "check --features="shumway,pdf""` ) 81 (e.g: `--features="shumway,pdf"` will run as `cargo watch -x "check --features="shumway,pdf""` )
81* `rust-analyzer.trace.server`: enables internal logging 82* `rust-analyzer.trace.server`: enables internal logging
82* `rust-analyzer.trace.cargo-watch`: enables cargo-watch logging 83* `rust-analyzer.trace.cargo-watch`: enables cargo-watch logging