aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_assists/src/assists/add_new.rs35
-rw-r--r--crates/ra_batch/src/lib.rs2
-rw-r--r--crates/ra_hir/src/code_model.rs4
-rw-r--r--crates/ra_hir/src/source_binder.rs4
-rw-r--r--crates/ra_hir_def/src/body/lower.rs4
-rw-r--r--crates/ra_hir_def/src/builtin_type.rs42
-rw-r--r--crates/ra_hir_def/src/data.rs4
-rw-r--r--crates/ra_hir_def/src/generics.rs6
-rw-r--r--crates/ra_hir_def/src/nameres/collector.rs4
-rw-r--r--crates/ra_hir_def/src/path.rs96
-rw-r--r--crates/ra_hir_def/src/resolver.rs16
-rw-r--r--crates/ra_hir_expand/src/builtin_derive.rs26
-rw-r--r--crates/ra_hir_expand/src/builtin_macro.rs16
-rw-r--r--crates/ra_hir_expand/src/name.rs164
-rw-r--r--crates/ra_hir_ty/src/autoderef.rs4
-rw-r--r--crates/ra_hir_ty/src/expr.rs4
-rw-r--r--crates/ra_hir_ty/src/infer.rs64
-rw-r--r--crates/ra_hir_ty/src/infer/expr.rs105
-rw-r--r--crates/ra_hir_ty/src/tests/traits.rs64
-rw-r--r--crates/ra_hir_ty/src/traits/builtin.rs6
-rw-r--r--crates/ra_hir_ty/src/utils.rs6
-rw-r--r--crates/ra_lsp_server/src/config.rs5
-rw-r--r--crates/ra_lsp_server/src/conv.rs5
-rw-r--r--crates/ra_lsp_server/src/main_loop.rs1
-rw-r--r--crates/ra_project_model/src/cargo_workspace.rs31
-rw-r--r--crates/ra_project_model/src/lib.rs14
26 files changed, 414 insertions, 318 deletions
diff --git a/crates/ra_assists/src/assists/add_new.rs b/crates/ra_assists/src/assists/add_new.rs
index d340cac8f..b2f946fac 100644
--- a/crates/ra_assists/src/assists/add_new.rs
+++ b/crates/ra_assists/src/assists/add_new.rs
@@ -139,43 +139,40 @@ fn find_struct_impl(
139 139
140 let struct_ty = { 140 let struct_ty = {
141 let src = InFile { file_id: ctx.frange.file_id.into(), value: strukt.clone() }; 141 let src = InFile { file_id: ctx.frange.file_id.into(), value: strukt.clone() };
142 hir::Struct::from_source(db, src).unwrap().ty(db) 142 hir::Struct::from_source(db, src)?.ty(db)
143 }; 143 };
144 144
145 let mut found_new_fn = false; 145 let block = module.descendants().filter_map(ast::ImplBlock::cast).find_map(|impl_blk| {
146
147 let block = module.descendants().filter_map(ast::ImplBlock::cast).find(|impl_blk| {
148 if found_new_fn {
149 return false;
150 }
151
152 let src = InFile { file_id: ctx.frange.file_id.into(), value: impl_blk.clone() }; 146 let src = InFile { file_id: ctx.frange.file_id.into(), value: impl_blk.clone() };
153 let blk = hir::ImplBlock::from_source(db, src).unwrap(); 147 let blk = hir::ImplBlock::from_source(db, src)?;
154 148
155 let same_ty = blk.target_ty(db) == struct_ty; 149 let same_ty = blk.target_ty(db) == struct_ty;
156 let not_trait_impl = blk.target_trait(db).is_none(); 150 let not_trait_impl = blk.target_trait(db).is_none();
157 151
158 if !(same_ty && not_trait_impl) { 152 if !(same_ty && not_trait_impl) {
159 return false; 153 None
154 } else {
155 Some(impl_blk)
160 } 156 }
161
162 found_new_fn = has_new_fn(impl_blk);
163 true
164 }); 157 });
165 158
166 if found_new_fn { 159 if let Some(ref impl_blk) = block {
167 None 160 if has_new_fn(impl_blk) {
168 } else { 161 return None;
169 Some(block) 162 }
170 } 163 }
164
165 Some(block)
171} 166}
172 167
173fn has_new_fn(imp: &ast::ImplBlock) -> bool { 168fn has_new_fn(imp: &ast::ImplBlock) -> bool {
174 if let Some(il) = imp.item_list() { 169 if let Some(il) = imp.item_list() {
175 for item in il.impl_items() { 170 for item in il.impl_items() {
176 if let ast::ImplItem::FnDef(f) = item { 171 if let ast::ImplItem::FnDef(f) = item {
177 if f.name().unwrap().text().eq_ignore_ascii_case("new") { 172 if let Some(name) = f.name() {
178 return true; 173 if name.text().eq_ignore_ascii_case("new") {
174 return true;
175 }
179 } 176 }
180 } 177 }
181 } 178 }
diff --git a/crates/ra_batch/src/lib.rs b/crates/ra_batch/src/lib.rs
index 2c9645c00..7744ba85a 100644
--- a/crates/ra_batch/src/lib.rs
+++ b/crates/ra_batch/src/lib.rs
@@ -22,7 +22,7 @@ fn vfs_root_to_id(r: ra_vfs::VfsRoot) -> SourceRootId {
22 22
23pub fn load_cargo(root: &Path) -> Result<(AnalysisHost, FxHashMap<SourceRootId, PackageRoot>)> { 23pub fn load_cargo(root: &Path) -> Result<(AnalysisHost, FxHashMap<SourceRootId, PackageRoot>)> {
24 let root = std::env::current_dir()?.join(root); 24 let root = std::env::current_dir()?.join(root);
25 let ws = ProjectWorkspace::discover(root.as_ref())?; 25 let ws = ProjectWorkspace::discover(root.as_ref(), &Default::default())?;
26 let project_roots = ws.to_roots(); 26 let project_roots = ws.to_roots();
27 let (sender, receiver) = unbounded(); 27 let (sender, receiver) = unbounded();
28 let sender = Box::new(move |t| sender.send(t).unwrap()); 28 let sender = Box::new(move |t| sender.send(t).unwrap());
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index c705d1630..7850ea9a7 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -17,7 +17,7 @@ use hir_def::{
17}; 17};
18use hir_expand::{ 18use hir_expand::{
19 diagnostics::DiagnosticSink, 19 diagnostics::DiagnosticSink,
20 name::{self, AsName}, 20 name::{name, AsName},
21 MacroDefId, 21 MacroDefId,
22}; 22};
23use hir_ty::{ 23use hir_ty::{
@@ -723,7 +723,7 @@ impl Local {
723 } 723 }
724 724
725 pub fn is_self(self, db: &impl HirDatabase) -> bool { 725 pub fn is_self(self, db: &impl HirDatabase) -> bool {
726 self.name(db) == Some(name::SELF_PARAM) 726 self.name(db) == Some(name![self])
727 } 727 }
728 728
729 pub fn is_mut(self, db: &impl HirDatabase) -> bool { 729 pub fn is_mut(self, db: &impl HirDatabase) -> bool {
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index d3cc5c423..f82242c3a 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -15,7 +15,7 @@ use hir_def::{
15 }, 15 },
16 expr::{ExprId, PatId}, 16 expr::{ExprId, PatId},
17 nameres::ModuleSource, 17 nameres::ModuleSource,
18 path::known, 18 path::path,
19 resolver::{self, resolver_for_scope, HasResolver, Resolver, TypeNs, ValueNs}, 19 resolver::{self, resolver_for_scope, HasResolver, Resolver, TypeNs, ValueNs},
20 AssocItemId, DefWithBodyId, 20 AssocItemId, DefWithBodyId,
21}; 21};
@@ -418,7 +418,7 @@ impl SourceAnalyzer {
418 /// Checks that particular type `ty` implements `std::future::Future`. 418 /// Checks that particular type `ty` implements `std::future::Future`.
419 /// This function is used in `.await` syntax completion. 419 /// This function is used in `.await` syntax completion.
420 pub fn impls_future(&self, db: &impl HirDatabase, ty: Type) -> bool { 420 pub fn impls_future(&self, db: &impl HirDatabase, ty: Type) -> bool {
421 let std_future_path = known::std_future_future(); 421 let std_future_path = path![std::future::Future];
422 422
423 let std_future_trait = match self.resolver.resolve_known_trait(db, &std_future_path) { 423 let std_future_trait = match self.resolver.resolve_known_trait(db, &std_future_path) {
424 Some(it) => it.into(), 424 Some(it) => it.into(),
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs
index cc068ff94..61193b4d8 100644
--- a/crates/ra_hir_def/src/body/lower.rs
+++ b/crates/ra_hir_def/src/body/lower.rs
@@ -2,7 +2,7 @@
2//! representation. 2//! representation.
3 3
4use either::Either; 4use either::Either;
5use hir_expand::name::{self, AsName, Name}; 5use hir_expand::name::{name, AsName, Name};
6use ra_arena::Arena; 6use ra_arena::Arena;
7use ra_syntax::{ 7use ra_syntax::{
8 ast::{ 8 ast::{
@@ -68,7 +68,7 @@ where
68 let ptr = AstPtr::new(&self_param); 68 let ptr = AstPtr::new(&self_param);
69 let param_pat = self.alloc_pat( 69 let param_pat = self.alloc_pat(
70 Pat::Bind { 70 Pat::Bind {
71 name: name::SELF_PARAM, 71 name: name![self],
72 mode: BindingAnnotation::Unannotated, 72 mode: BindingAnnotation::Unannotated,
73 subpat: None, 73 subpat: None,
74 }, 74 },
diff --git a/crates/ra_hir_def/src/builtin_type.rs b/crates/ra_hir_def/src/builtin_type.rs
index 5e8157144..d14901a9b 100644
--- a/crates/ra_hir_def/src/builtin_type.rs
+++ b/crates/ra_hir_def/src/builtin_type.rs
@@ -5,7 +5,7 @@
5 5
6use std::fmt; 6use std::fmt;
7 7
8use hir_expand::name::{self, Name}; 8use hir_expand::name::{name, Name};
9 9
10#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] 10#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
11pub enum Signedness { 11pub enum Signedness {
@@ -52,26 +52,26 @@ pub enum BuiltinType {
52impl BuiltinType { 52impl BuiltinType {
53 #[rustfmt::skip] 53 #[rustfmt::skip]
54 pub const ALL: &'static [(Name, BuiltinType)] = &[ 54 pub const ALL: &'static [(Name, BuiltinType)] = &[
55 (name::CHAR, BuiltinType::Char), 55 (name![char], BuiltinType::Char),
56 (name::BOOL, BuiltinType::Bool), 56 (name![bool], BuiltinType::Bool),
57 (name::STR, BuiltinType::Str ), 57 (name![str], BuiltinType::Str),
58 58
59 (name::ISIZE, BuiltinType::Int(BuiltinInt::ISIZE)), 59 (name![isize], BuiltinType::Int(BuiltinInt::ISIZE)),
60 (name::I8, BuiltinType::Int(BuiltinInt::I8)), 60 (name![i8], BuiltinType::Int(BuiltinInt::I8)),
61 (name::I16, BuiltinType::Int(BuiltinInt::I16)), 61 (name![i16], BuiltinType::Int(BuiltinInt::I16)),
62 (name::I32, BuiltinType::Int(BuiltinInt::I32)), 62 (name![i32], BuiltinType::Int(BuiltinInt::I32)),
63 (name::I64, BuiltinType::Int(BuiltinInt::I64)), 63 (name![i64], BuiltinType::Int(BuiltinInt::I64)),
64 (name::I128, BuiltinType::Int(BuiltinInt::I128)), 64 (name![i128], BuiltinType::Int(BuiltinInt::I128)),
65 65
66 (name::USIZE, BuiltinType::Int(BuiltinInt::USIZE)), 66 (name![usize], BuiltinType::Int(BuiltinInt::USIZE)),
67 (name::U8, BuiltinType::Int(BuiltinInt::U8)), 67 (name![u8], BuiltinType::Int(BuiltinInt::U8)),
68 (name::U16, BuiltinType::Int(BuiltinInt::U16)), 68 (name![u16], BuiltinType::Int(BuiltinInt::U16)),
69 (name::U32, BuiltinType::Int(BuiltinInt::U32)), 69 (name![u32], BuiltinType::Int(BuiltinInt::U32)),
70 (name::U64, BuiltinType::Int(BuiltinInt::U64)), 70 (name![u64], BuiltinType::Int(BuiltinInt::U64)),
71 (name::U128, BuiltinType::Int(BuiltinInt::U128)), 71 (name![u128], BuiltinType::Int(BuiltinInt::U128)),
72 72
73 (name::F32, BuiltinType::Float(BuiltinFloat::F32)), 73 (name![f32], BuiltinType::Float(BuiltinFloat::F32)),
74 (name::F64, BuiltinType::Float(BuiltinFloat::F64)), 74 (name![f64], BuiltinType::Float(BuiltinFloat::F64)),
75 ]; 75 ];
76} 76}
77 77
diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs
index b2dac183e..4f4ef57cc 100644
--- a/crates/ra_hir_def/src/data.rs
+++ b/crates/ra_hir_def/src/data.rs
@@ -3,7 +3,7 @@
3use std::sync::Arc; 3use std::sync::Arc;
4 4
5use hir_expand::{ 5use hir_expand::{
6 name::{self, AsName, Name}, 6 name::{name, AsName, Name},
7 AstId, 7 AstId,
8}; 8};
9use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner}; 9use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner};
@@ -37,7 +37,7 @@ impl FunctionData {
37 let self_type = if let Some(type_ref) = self_param.ascribed_type() { 37 let self_type = if let Some(type_ref) = self_param.ascribed_type() {
38 TypeRef::from_ast(type_ref) 38 TypeRef::from_ast(type_ref)
39 } else { 39 } else {
40 let self_type = TypeRef::Path(name::SELF_TYPE.into()); 40 let self_type = TypeRef::Path(name![Self].into());
41 match self_param.kind() { 41 match self_param.kind() {
42 ast::SelfParamKind::Owned => self_type, 42 ast::SelfParamKind::Owned => self_type,
43 ast::SelfParamKind::Ref => { 43 ast::SelfParamKind::Ref => {
diff --git a/crates/ra_hir_def/src/generics.rs b/crates/ra_hir_def/src/generics.rs
index e502dd798..e9c28c730 100644
--- a/crates/ra_hir_def/src/generics.rs
+++ b/crates/ra_hir_def/src/generics.rs
@@ -6,7 +6,7 @@ use std::sync::Arc;
6 6
7use either::Either; 7use either::Either;
8use hir_expand::{ 8use hir_expand::{
9 name::{self, AsName, Name}, 9 name::{name, AsName, Name},
10 InFile, 10 InFile,
11}; 11};
12use ra_arena::{map::ArenaMap, Arena}; 12use ra_arena::{map::ArenaMap, Arena};
@@ -90,11 +90,11 @@ impl GenericParams {
90 90
91 // traits get the Self type as an implicit first type parameter 91 // traits get the Self type as an implicit first type parameter
92 let self_param_id = 92 let self_param_id =
93 generics.types.alloc(TypeParamData { name: name::SELF_TYPE, default: None }); 93 generics.types.alloc(TypeParamData { name: name![Self], default: None });
94 sm.insert(self_param_id, Either::Left(src.value.clone())); 94 sm.insert(self_param_id, Either::Left(src.value.clone()));
95 // add super traits as bounds on Self 95 // add super traits as bounds on Self
96 // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar 96 // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar
97 let self_param = TypeRef::Path(name::SELF_TYPE.into()); 97 let self_param = TypeRef::Path(name![Self].into());
98 generics.fill_bounds(&src.value, self_param); 98 generics.fill_bounds(&src.value, self_param);
99 99
100 generics.fill(&mut sm, &src.value); 100 generics.fill(&mut sm, &src.value);
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs
index 04aadead1..5d7469a6e 100644
--- a/crates/ra_hir_def/src/nameres/collector.rs
+++ b/crates/ra_hir_def/src/nameres/collector.rs
@@ -6,7 +6,7 @@
6use hir_expand::{ 6use hir_expand::{
7 builtin_derive::find_builtin_derive, 7 builtin_derive::find_builtin_derive,
8 builtin_macro::find_builtin_macro, 8 builtin_macro::find_builtin_macro,
9 name::{self, AsName, Name}, 9 name::{name, AsName, Name},
10 HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, 10 HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
11}; 11};
12use ra_cfg::CfgOptions; 12use ra_cfg::CfgOptions;
@@ -918,7 +918,7 @@ where
918} 918}
919 919
920fn is_macro_rules(path: &Path) -> bool { 920fn is_macro_rules(path: &Path) -> bool {
921 path.as_ident() == Some(&name::MACRO_RULES) 921 path.as_ident() == Some(&name![macro_rules])
922} 922}
923 923
924#[cfg(test)] 924#[cfg(test)]
diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs
index ec9d13e82..1e9eb14ea 100644
--- a/crates/ra_hir_def/src/path.rs
+++ b/crates/ra_hir_def/src/path.rs
@@ -6,7 +6,7 @@ use std::{iter, sync::Arc};
6use either::Either; 6use either::Either;
7use hir_expand::{ 7use hir_expand::{
8 hygiene::Hygiene, 8 hygiene::Hygiene,
9 name::{self, AsName, Name}, 9 name::{name, AsName, Name},
10}; 10};
11use ra_db::CrateId; 11use ra_db::CrateId;
12use ra_syntax::{ 12use ra_syntax::{
@@ -76,10 +76,7 @@ impl Path {
76 } 76 }
77 } 77 }
78 78
79 pub(crate) fn from_simple_segments( 79 pub fn from_simple_segments(kind: PathKind, segments: impl IntoIterator<Item = Name>) -> Path {
80 kind: PathKind,
81 segments: impl IntoIterator<Item = Name>,
82 ) -> Path {
83 Path { 80 Path {
84 kind, 81 kind,
85 segments: segments 82 segments: segments
@@ -276,7 +273,7 @@ impl GenericArgs {
276 } 273 }
277 if let Some(ret_type) = ret_type { 274 if let Some(ret_type) = ret_type {
278 let type_ref = TypeRef::from_ast_opt(ret_type.type_ref()); 275 let type_ref = TypeRef::from_ast_opt(ret_type.type_ref());
279 bindings.push((name::OUTPUT_TYPE, type_ref)) 276 bindings.push((name![Output], type_ref))
280 } 277 }
281 if args.is_empty() && bindings.is_empty() { 278 if args.is_empty() && bindings.is_empty() {
282 None 279 None
@@ -296,61 +293,36 @@ impl From<Name> for Path {
296 } 293 }
297} 294}
298 295
299pub mod known { 296pub use hir_expand::name as __name;
300 use hir_expand::name; 297
301 298#[macro_export]
302 use super::{Path, PathKind}; 299macro_rules! __known_path {
303 300 (std::iter::IntoIterator) => {};
304 pub fn std_iter_into_iterator() -> Path { 301 (std::result::Result) => {};
305 Path::from_simple_segments( 302 (std::ops::Range) => {};
306 PathKind::Abs, 303 (std::ops::RangeFrom) => {};
307 vec![name::STD, name::ITER, name::INTO_ITERATOR_TYPE], 304 (std::ops::RangeFull) => {};
308 ) 305 (std::ops::RangeTo) => {};
309 } 306 (std::ops::RangeToInclusive) => {};
310 307 (std::ops::RangeInclusive) => {};
311 pub fn std_ops_try() -> Path { 308 (std::boxed::Box) => {};
312 Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::OPS, name::TRY_TYPE]) 309 (std::future::Future) => {};
313 } 310 (std::ops::Try) => {};
314 311 (std::ops::Neg) => {};
315 pub fn std_ops_range() -> Path { 312 (std::ops::Not) => {};
316 Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::OPS, name::RANGE_TYPE]) 313 ($path:path) => {
317 } 314 compile_error!("Please register your known path in the path module")
318 315 };
319 pub fn std_ops_range_from() -> Path { 316}
320 Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::OPS, name::RANGE_FROM_TYPE])
321 }
322
323 pub fn std_ops_range_full() -> Path {
324 Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::OPS, name::RANGE_FULL_TYPE])
325 }
326
327 pub fn std_ops_range_inclusive() -> Path {
328 Path::from_simple_segments(
329 PathKind::Abs,
330 vec![name::STD, name::OPS, name::RANGE_INCLUSIVE_TYPE],
331 )
332 }
333
334 pub fn std_ops_range_to() -> Path {
335 Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::OPS, name::RANGE_TO_TYPE])
336 }
337
338 pub fn std_ops_range_to_inclusive() -> Path {
339 Path::from_simple_segments(
340 PathKind::Abs,
341 vec![name::STD, name::OPS, name::RANGE_TO_INCLUSIVE_TYPE],
342 )
343 }
344
345 pub fn std_result_result() -> Path {
346 Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::RESULT, name::RESULT_TYPE])
347 }
348
349 pub fn std_future_future() -> Path {
350 Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::FUTURE, name::FUTURE_TYPE])
351 }
352 317
353 pub fn std_boxed_box() -> Path { 318#[macro_export]
354 Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::BOXED, name::BOX_TYPE]) 319macro_rules! __path {
355 } 320 ($start:ident $(:: $seg:ident)*) => ({
321 $crate::__known_path!($start $(:: $seg)*);
322 $crate::path::Path::from_simple_segments($crate::path::PathKind::Abs, vec![
323 $crate::path::__name![$start], $($crate::path::__name![$seg],)*
324 ])
325 });
356} 326}
327
328pub use crate::__path as path;
diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs
index 17b2169d2..b6d595a20 100644
--- a/crates/ra_hir_def/src/resolver.rs
+++ b/crates/ra_hir_def/src/resolver.rs
@@ -2,7 +2,7 @@
2use std::sync::Arc; 2use std::sync::Arc;
3 3
4use hir_expand::{ 4use hir_expand::{
5 name::{self, Name}, 5 name::{name, Name},
6 MacroDefId, 6 MacroDefId,
7}; 7};
8use ra_db::CrateId; 8use ra_db::CrateId;
@@ -163,13 +163,13 @@ impl Resolver {
163 } 163 }
164 } 164 }
165 Scope::ImplBlockScope(impl_) => { 165 Scope::ImplBlockScope(impl_) => {
166 if first_name == &name::SELF_TYPE { 166 if first_name == &name![Self] {
167 let idx = if path.segments.len() == 1 { None } else { Some(1) }; 167 let idx = if path.segments.len() == 1 { None } else { Some(1) };
168 return Some((TypeNs::SelfType(*impl_), idx)); 168 return Some((TypeNs::SelfType(*impl_), idx));
169 } 169 }
170 } 170 }
171 Scope::AdtScope(adt) => { 171 Scope::AdtScope(adt) => {
172 if first_name == &name::SELF_TYPE { 172 if first_name == &name![Self] {
173 let idx = if path.segments.len() == 1 { None } else { Some(1) }; 173 let idx = if path.segments.len() == 1 { None } else { Some(1) };
174 return Some((TypeNs::AdtSelfType(*adt), idx)); 174 return Some((TypeNs::AdtSelfType(*adt), idx));
175 } 175 }
@@ -223,7 +223,7 @@ impl Resolver {
223 return None; 223 return None;
224 } 224 }
225 let n_segments = path.segments.len(); 225 let n_segments = path.segments.len();
226 let tmp = name::SELF_PARAM; 226 let tmp = name![self];
227 let first_name = if path.is_self() { &tmp } else { &path.segments.first()?.name }; 227 let first_name = if path.is_self() { &tmp } else { &path.segments.first()?.name };
228 let skip_to_mod = path.kind != PathKind::Plain && !path.is_self(); 228 let skip_to_mod = path.kind != PathKind::Plain && !path.is_self();
229 for scope in self.scopes.iter().rev() { 229 for scope in self.scopes.iter().rev() {
@@ -259,13 +259,13 @@ impl Resolver {
259 Scope::GenericParams { .. } => continue, 259 Scope::GenericParams { .. } => continue,
260 260
261 Scope::ImplBlockScope(impl_) if n_segments > 1 => { 261 Scope::ImplBlockScope(impl_) if n_segments > 1 => {
262 if first_name == &name::SELF_TYPE { 262 if first_name == &name![Self] {
263 let ty = TypeNs::SelfType(*impl_); 263 let ty = TypeNs::SelfType(*impl_);
264 return Some(ResolveValueResult::Partial(ty, 1)); 264 return Some(ResolveValueResult::Partial(ty, 1));
265 } 265 }
266 } 266 }
267 Scope::AdtScope(adt) if n_segments > 1 => { 267 Scope::AdtScope(adt) if n_segments > 1 => {
268 if first_name == &name::SELF_TYPE { 268 if first_name == &name![Self] {
269 let ty = TypeNs::AdtSelfType(*adt); 269 let ty = TypeNs::AdtSelfType(*adt);
270 return Some(ResolveValueResult::Partial(ty, 1)); 270 return Some(ResolveValueResult::Partial(ty, 1));
271 } 271 }
@@ -439,10 +439,10 @@ impl Scope {
439 } 439 }
440 } 440 }
441 Scope::ImplBlockScope(i) => { 441 Scope::ImplBlockScope(i) => {
442 f(name::SELF_TYPE, ScopeDef::ImplSelfType((*i).into())); 442 f(name![Self], ScopeDef::ImplSelfType((*i).into()));
443 } 443 }
444 Scope::AdtScope(i) => { 444 Scope::AdtScope(i) => {
445 f(name::SELF_TYPE, ScopeDef::AdtSelfType((*i).into())); 445 f(name![Self], ScopeDef::AdtSelfType((*i).into()));
446 } 446 }
447 Scope::ExprScope(scope) => { 447 Scope::ExprScope(scope) => {
448 scope.expr_scopes.entries(scope.scope_id).iter().for_each(|e| { 448 scope.expr_scopes.entries(scope.scope_id).iter().for_each(|e| {
diff --git a/crates/ra_hir_expand/src/builtin_derive.rs b/crates/ra_hir_expand/src/builtin_derive.rs
index 574637602..b26441253 100644
--- a/crates/ra_hir_expand/src/builtin_derive.rs
+++ b/crates/ra_hir_expand/src/builtin_derive.rs
@@ -12,10 +12,10 @@ use crate::db::AstDatabase;
12use crate::{name, quote, MacroCallId, MacroDefId, MacroDefKind}; 12use crate::{name, quote, MacroCallId, MacroDefId, MacroDefKind};
13 13
14macro_rules! register_builtin { 14macro_rules! register_builtin {
15 ( $(($name:ident, $kind: ident) => $expand:ident),* ) => { 15 ( $($trait:ident => $expand:ident),* ) => {
16 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 16 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
17 pub enum BuiltinDeriveExpander { 17 pub enum BuiltinDeriveExpander {
18 $($kind),* 18 $($trait),*
19 } 19 }
20 20
21 impl BuiltinDeriveExpander { 21 impl BuiltinDeriveExpander {
@@ -26,7 +26,7 @@ macro_rules! register_builtin {
26 tt: &tt::Subtree, 26 tt: &tt::Subtree,
27 ) -> Result<tt::Subtree, mbe::ExpandError> { 27 ) -> Result<tt::Subtree, mbe::ExpandError> {
28 let expander = match *self { 28 let expander = match *self {
29 $( BuiltinDeriveExpander::$kind => $expand, )* 29 $( BuiltinDeriveExpander::$trait => $expand, )*
30 }; 30 };
31 expander(db, id, tt) 31 expander(db, id, tt)
32 } 32 }
@@ -34,7 +34,7 @@ macro_rules! register_builtin {
34 34
35 pub fn find_builtin_derive(ident: &name::Name) -> Option<MacroDefId> { 35 pub fn find_builtin_derive(ident: &name::Name) -> Option<MacroDefId> {
36 let kind = match ident { 36 let kind = match ident {
37 $( id if id == &name::$name => BuiltinDeriveExpander::$kind, )* 37 $( id if id == &name::name![$trait] => BuiltinDeriveExpander::$trait, )*
38 _ => return None, 38 _ => return None,
39 }; 39 };
40 40
@@ -44,15 +44,15 @@ macro_rules! register_builtin {
44} 44}
45 45
46register_builtin! { 46register_builtin! {
47 (COPY_TRAIT, Copy) => copy_expand, 47 Copy => copy_expand,
48 (CLONE_TRAIT, Clone) => clone_expand, 48 Clone => clone_expand,
49 (DEFAULT_TRAIT, Default) => default_expand, 49 Default => default_expand,
50 (DEBUG_TRAIT, Debug) => debug_expand, 50 Debug => debug_expand,
51 (HASH_TRAIT, Hash) => hash_expand, 51 Hash => hash_expand,
52 (ORD_TRAIT, Ord) => ord_expand, 52 Ord => ord_expand,
53 (PARTIAL_ORD_TRAIT, PartialOrd) => partial_ord_expand, 53 PartialOrd => partial_ord_expand,
54 (EQ_TRAIT, Eq) => eq_expand, 54 Eq => eq_expand,
55 (PARTIAL_EQ_TRAIT, PartialEq) => partial_eq_expand 55 PartialEq => partial_eq_expand
56} 56}
57 57
58struct BasicAdtInfo { 58struct BasicAdtInfo {
diff --git a/crates/ra_hir_expand/src/builtin_macro.rs b/crates/ra_hir_expand/src/builtin_macro.rs
index be5f3cbe3..d2b3d769e 100644
--- a/crates/ra_hir_expand/src/builtin_macro.rs
+++ b/crates/ra_hir_expand/src/builtin_macro.rs
@@ -34,7 +34,7 @@ macro_rules! register_builtin {
34 ast_id: AstId<ast::MacroCall>, 34 ast_id: AstId<ast::MacroCall>,
35 ) -> Option<MacroDefId> { 35 ) -> Option<MacroDefId> {
36 let kind = match ident { 36 let kind = match ident {
37 $( id if id == &name::$name => BuiltinFnLikeExpander::$kind, )* 37 $( id if id == &name::name![$name] => BuiltinFnLikeExpander::$kind, )*
38 _ => return None, 38 _ => return None,
39 }; 39 };
40 40
@@ -44,15 +44,15 @@ macro_rules! register_builtin {
44} 44}
45 45
46register_builtin! { 46register_builtin! {
47 (COLUMN_MACRO, Column) => column_expand, 47 (column, Column) => column_expand,
48 (COMPILE_ERROR_MACRO, CompileError) => compile_error_expand, 48 (compile_error, CompileError) => compile_error_expand,
49 (FILE_MACRO, File) => file_expand, 49 (file, File) => file_expand,
50 (LINE_MACRO, Line) => line_expand, 50 (line, Line) => line_expand,
51 (STRINGIFY_MACRO, Stringify) => stringify_expand, 51 (stringify, Stringify) => stringify_expand,
52 (FORMAT_ARGS_MACRO, FormatArgs) => format_args_expand, 52 (format_args, FormatArgs) => format_args_expand,
53 // format_args_nl only differs in that it adds a newline in the end, 53 // format_args_nl only differs in that it adds a newline in the end,
54 // so we use the same stub expansion for now 54 // so we use the same stub expansion for now
55 (FORMAT_ARGS_NL_MACRO, FormatArgsNl) => format_args_expand 55 (format_args_nl, FormatArgsNl) => format_args_expand
56} 56}
57 57
58fn to_line_number(db: &dyn AstDatabase, file: HirFileId, pos: TextUnit) -> usize { 58fn to_line_number(db: &dyn AstDatabase, file: HirFileId, pos: TextUnit) -> usize {
diff --git a/crates/ra_hir_expand/src/name.rs b/crates/ra_hir_expand/src/name.rs
index 4f2f702c0..59d8214fd 100644
--- a/crates/ra_hir_expand/src/name.rs
+++ b/crates/ra_hir_expand/src/name.rs
@@ -104,71 +104,99 @@ impl AsName for ra_db::Dependency {
104 } 104 }
105} 105}
106 106
107// Primitives 107pub mod known {
108pub const ISIZE: Name = Name::new_inline_ascii(b"isize"); 108 macro_rules! known_names {
109pub const I8: Name = Name::new_inline_ascii(b"i8"); 109 ($($ident:ident),* $(,)?) => {
110pub const I16: Name = Name::new_inline_ascii(b"i16"); 110 $(
111pub const I32: Name = Name::new_inline_ascii(b"i32"); 111 #[allow(bad_style)]
112pub const I64: Name = Name::new_inline_ascii(b"i64"); 112 pub const $ident: super::Name =
113pub const I128: Name = Name::new_inline_ascii(b"i128"); 113 super::Name::new_inline_ascii(stringify!($ident).as_bytes());
114pub const USIZE: Name = Name::new_inline_ascii(b"usize"); 114 )*
115pub const U8: Name = Name::new_inline_ascii(b"u8"); 115 };
116pub const U16: Name = Name::new_inline_ascii(b"u16"); 116 }
117pub const U32: Name = Name::new_inline_ascii(b"u32"); 117
118pub const U64: Name = Name::new_inline_ascii(b"u64"); 118 known_names!(
119pub const U128: Name = Name::new_inline_ascii(b"u128"); 119 // Primitives
120pub const F32: Name = Name::new_inline_ascii(b"f32"); 120 isize,
121pub const F64: Name = Name::new_inline_ascii(b"f64"); 121 i8,
122pub const BOOL: Name = Name::new_inline_ascii(b"bool"); 122 i16,
123pub const CHAR: Name = Name::new_inline_ascii(b"char"); 123 i32,
124pub const STR: Name = Name::new_inline_ascii(b"str"); 124 i64,
125 125 i128,
126// Special names 126 usize,
127pub const SELF_PARAM: Name = Name::new_inline_ascii(b"self"); 127 u8,
128pub const SELF_TYPE: Name = Name::new_inline_ascii(b"Self"); 128 u16,
129pub const MACRO_RULES: Name = Name::new_inline_ascii(b"macro_rules"); 129 u32,
130 130 u64,
131// Components of known path (value or mod name) 131 u128,
132pub const STD: Name = Name::new_inline_ascii(b"std"); 132 f32,
133pub const ITER: Name = Name::new_inline_ascii(b"iter"); 133 f64,
134pub const OPS: Name = Name::new_inline_ascii(b"ops"); 134 bool,
135pub const FUTURE: Name = Name::new_inline_ascii(b"future"); 135 char,
136pub const RESULT: Name = Name::new_inline_ascii(b"result"); 136 str,
137pub const BOXED: Name = Name::new_inline_ascii(b"boxed"); 137 // Special names
138 138 macro_rules,
139// Components of known path (type name) 139 // Components of known path (value or mod name)
140pub const INTO_ITERATOR_TYPE: Name = Name::new_inline_ascii(b"IntoIterator"); 140 std,
141pub const ITEM_TYPE: Name = Name::new_inline_ascii(b"Item"); 141 iter,
142pub const TRY_TYPE: Name = Name::new_inline_ascii(b"Try"); 142 ops,
143pub const OK_TYPE: Name = Name::new_inline_ascii(b"Ok"); 143 future,
144pub const FUTURE_TYPE: Name = Name::new_inline_ascii(b"Future"); 144 result,
145pub const RESULT_TYPE: Name = Name::new_inline_ascii(b"Result"); 145 boxed,
146pub const OUTPUT_TYPE: Name = Name::new_inline_ascii(b"Output"); 146 // Components of known path (type name)
147pub const TARGET_TYPE: Name = Name::new_inline_ascii(b"Target"); 147 IntoIterator,
148pub const BOX_TYPE: Name = Name::new_inline_ascii(b"Box"); 148 Item,
149pub const RANGE_FROM_TYPE: Name = Name::new_inline_ascii(b"RangeFrom"); 149 Try,
150pub const RANGE_FULL_TYPE: Name = Name::new_inline_ascii(b"RangeFull"); 150 Ok,
151pub const RANGE_INCLUSIVE_TYPE: Name = Name::new_inline_ascii(b"RangeInclusive"); 151 Future,
152pub const RANGE_TO_INCLUSIVE_TYPE: Name = Name::new_inline_ascii(b"RangeToInclusive"); 152 Result,
153pub const RANGE_TO_TYPE: Name = Name::new_inline_ascii(b"RangeTo"); 153 Output,
154pub const RANGE_TYPE: Name = Name::new_inline_ascii(b"Range"); 154 Target,
155 155 Box,
156// Builtin Macros 156 RangeFrom,
157pub const FILE_MACRO: Name = Name::new_inline_ascii(b"file"); 157 RangeFull,
158pub const COLUMN_MACRO: Name = Name::new_inline_ascii(b"column"); 158 RangeInclusive,
159pub const COMPILE_ERROR_MACRO: Name = Name::new_inline_ascii(b"compile_error"); 159 RangeToInclusive,
160pub const LINE_MACRO: Name = Name::new_inline_ascii(b"line"); 160 RangeTo,
161pub const STRINGIFY_MACRO: Name = Name::new_inline_ascii(b"stringify"); 161 Range,
162pub const FORMAT_ARGS_MACRO: Name = Name::new_inline_ascii(b"format_args"); 162 Neg,
163pub const FORMAT_ARGS_NL_MACRO: Name = Name::new_inline_ascii(b"format_args_nl"); 163 Not,
164 164 // Builtin macros
165// Builtin derives 165 file,
166pub const COPY_TRAIT: Name = Name::new_inline_ascii(b"Copy"); 166 column,
167pub const CLONE_TRAIT: Name = Name::new_inline_ascii(b"Clone"); 167 compile_error,
168pub const DEFAULT_TRAIT: Name = Name::new_inline_ascii(b"Default"); 168 line,
169pub const DEBUG_TRAIT: Name = Name::new_inline_ascii(b"Debug"); 169 stringify,
170pub const HASH_TRAIT: Name = Name::new_inline_ascii(b"Hash"); 170 format_args,
171pub const ORD_TRAIT: Name = Name::new_inline_ascii(b"Ord"); 171 format_args_nl,
172pub const PARTIAL_ORD_TRAIT: Name = Name::new_inline_ascii(b"PartialOrd"); 172 // Builtin derives
173pub const EQ_TRAIT: Name = Name::new_inline_ascii(b"Eq"); 173 Copy,
174pub const PARTIAL_EQ_TRAIT: Name = Name::new_inline_ascii(b"PartialEq"); 174 Clone,
175 Default,
176 Debug,
177 Hash,
178 Ord,
179 PartialOrd,
180 Eq,
181 PartialEq,
182 );
183
184 // self/Self cannot be used as an identifier
185 pub const SELF_PARAM: super::Name = super::Name::new_inline_ascii(b"self");
186 pub const SELF_TYPE: super::Name = super::Name::new_inline_ascii(b"Self");
187
188 #[macro_export]
189 macro_rules! name {
190 (self) => {
191 $crate::name::known::SELF_PARAM
192 };
193 (Self) => {
194 $crate::name::known::SELF_TYPE
195 };
196 ($ident:ident) => {
197 $crate::name::known::$ident
198 };
199 }
200}
201
202pub use crate::name;
diff --git a/crates/ra_hir_ty/src/autoderef.rs b/crates/ra_hir_ty/src/autoderef.rs
index d557962b4..ee48fa537 100644
--- a/crates/ra_hir_ty/src/autoderef.rs
+++ b/crates/ra_hir_ty/src/autoderef.rs
@@ -6,7 +6,7 @@
6use std::iter::successors; 6use std::iter::successors;
7 7
8use hir_def::lang_item::LangItemTarget; 8use hir_def::lang_item::LangItemTarget;
9use hir_expand::name; 9use hir_expand::name::name;
10use log::{info, warn}; 10use log::{info, warn};
11use ra_db::CrateId; 11use ra_db::CrateId;
12 12
@@ -52,7 +52,7 @@ fn deref_by_trait(
52 LangItemTarget::TraitId(it) => it, 52 LangItemTarget::TraitId(it) => it,
53 _ => return None, 53 _ => return None,
54 }; 54 };
55 let target = db.trait_data(deref_trait).associated_type_by_name(&name::TARGET_TYPE)?; 55 let target = db.trait_data(deref_trait).associated_type_by_name(&name![Target])?;
56 56
57 let generic_params = generics(db, target.into()); 57 let generic_params = generics(db, target.into());
58 if generic_params.len() != 1 { 58 if generic_params.len() != 1 {
diff --git a/crates/ra_hir_ty/src/expr.rs b/crates/ra_hir_ty/src/expr.rs
index d2bd64e5c..f752a9f09 100644
--- a/crates/ra_hir_ty/src/expr.rs
+++ b/crates/ra_hir_ty/src/expr.rs
@@ -3,7 +3,7 @@
3use std::sync::Arc; 3use std::sync::Arc;
4 4
5use hir_def::{ 5use hir_def::{
6 path::{known, Path}, 6 path::{path, Path},
7 resolver::HasResolver, 7 resolver::HasResolver,
8 AdtId, FunctionId, 8 AdtId, FunctionId,
9}; 9};
@@ -124,7 +124,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
124 None => return, 124 None => return,
125 }; 125 };
126 126
127 let std_result_path = known::std_result_result(); 127 let std_result_path = path![std::result::Result];
128 128
129 let resolver = self.func.resolver(db); 129 let resolver = self.func.resolver(db);
130 let std_result_enum = match resolver.resolve_known_enum(db, &std_result_path) { 130 let std_result_enum = match resolver.resolve_known_enum(db, &std_result_path) {
diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs
index d16f1eb46..f1b7e9442 100644
--- a/crates/ra_hir_ty/src/infer.rs
+++ b/crates/ra_hir_ty/src/infer.rs
@@ -24,20 +24,20 @@ use hir_def::{
24 body::Body, 24 body::Body,
25 data::{ConstData, FunctionData}, 25 data::{ConstData, FunctionData},
26 expr::{BindingAnnotation, ExprId, PatId}, 26 expr::{BindingAnnotation, ExprId, PatId},
27 path::{known, Path}, 27 path::{path, Path},
28 resolver::{HasResolver, Resolver, TypeNs}, 28 resolver::{HasResolver, Resolver, TypeNs},
29 type_ref::{Mutability, TypeRef}, 29 type_ref::{Mutability, TypeRef},
30 AdtId, AssocItemId, DefWithBodyId, FunctionId, StructFieldId, TypeAliasId, VariantId, 30 AdtId, AssocItemId, DefWithBodyId, FunctionId, StructFieldId, TypeAliasId, VariantId,
31}; 31};
32use hir_expand::{diagnostics::DiagnosticSink, name}; 32use hir_expand::{diagnostics::DiagnosticSink, name::name};
33use ra_arena::map::ArenaMap; 33use ra_arena::map::ArenaMap;
34use ra_prof::profile; 34use ra_prof::profile;
35 35
36use super::{ 36use super::{
37 primitive::{FloatTy, IntTy}, 37 primitive::{FloatTy, IntTy},
38 traits::{Guidance, Obligation, ProjectionPredicate, Solution}, 38 traits::{Guidance, Obligation, ProjectionPredicate, Solution},
39 ApplicationTy, InEnvironment, ProjectionTy, TraitEnvironment, TraitRef, Ty, TypeCtor, TypeWalk, 39 ApplicationTy, InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeCtor,
40 Uncertain, 40 TypeWalk, Uncertain,
41}; 41};
42use crate::{db::HirDatabase, infer::diagnostics::InferenceDiagnostic}; 42use crate::{db::HirDatabase, infer::diagnostics::InferenceDiagnostic};
43 43
@@ -338,6 +338,24 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
338 self.table.resolve_ty_shallow(ty) 338 self.table.resolve_ty_shallow(ty)
339 } 339 }
340 340
341 fn resolve_associated_type(&mut self, inner_ty: Ty, assoc_ty: Option<TypeAliasId>) -> Ty {
342 match assoc_ty {
343 Some(res_assoc_ty) => {
344 let ty = self.table.new_type_var();
345 let projection = ProjectionPredicate {
346 ty: ty.clone(),
347 projection_ty: ProjectionTy {
348 associated_ty: res_assoc_ty,
349 parameters: Substs::single(inner_ty),
350 },
351 };
352 self.obligations.push(Obligation::Projection(projection));
353 self.resolve_ty_as_possible(ty)
354 }
355 None => Ty::Unknown,
356 }
357 }
358
341 /// Recurses through the given type, normalizing associated types mentioned 359 /// Recurses through the given type, normalizing associated types mentioned
342 /// in it by replacing them by type variables and registering obligations to 360 /// in it by replacing them by type variables and registering obligations to
343 /// resolve later. This should be done once for every type we get from some 361 /// resolve later. This should be done once for every type we get from some
@@ -404,61 +422,73 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
404 } 422 }
405 423
406 fn resolve_into_iter_item(&self) -> Option<TypeAliasId> { 424 fn resolve_into_iter_item(&self) -> Option<TypeAliasId> {
407 let path = known::std_iter_into_iterator(); 425 let path = path![std::iter::IntoIterator];
408 let trait_ = self.resolver.resolve_known_trait(self.db, &path)?; 426 let trait_ = self.resolver.resolve_known_trait(self.db, &path)?;
409 self.db.trait_data(trait_).associated_type_by_name(&name::ITEM_TYPE) 427 self.db.trait_data(trait_).associated_type_by_name(&name![Item])
410 } 428 }
411 429
412 fn resolve_ops_try_ok(&self) -> Option<TypeAliasId> { 430 fn resolve_ops_try_ok(&self) -> Option<TypeAliasId> {
413 let path = known::std_ops_try(); 431 let path = path![std::ops::Try];
432 let trait_ = self.resolver.resolve_known_trait(self.db, &path)?;
433 self.db.trait_data(trait_).associated_type_by_name(&name![Ok])
434 }
435
436 fn resolve_ops_neg_output(&self) -> Option<TypeAliasId> {
437 let path = path![std::ops::Neg];
438 let trait_ = self.resolver.resolve_known_trait(self.db, &path)?;
439 self.db.trait_data(trait_).associated_type_by_name(&name![Output])
440 }
441
442 fn resolve_ops_not_output(&self) -> Option<TypeAliasId> {
443 let path = path![std::ops::Not];
414 let trait_ = self.resolver.resolve_known_trait(self.db, &path)?; 444 let trait_ = self.resolver.resolve_known_trait(self.db, &path)?;
415 self.db.trait_data(trait_).associated_type_by_name(&name::OK_TYPE) 445 self.db.trait_data(trait_).associated_type_by_name(&name![Output])
416 } 446 }
417 447
418 fn resolve_future_future_output(&self) -> Option<TypeAliasId> { 448 fn resolve_future_future_output(&self) -> Option<TypeAliasId> {
419 let path = known::std_future_future(); 449 let path = path![std::future::Future];
420 let trait_ = self.resolver.resolve_known_trait(self.db, &path)?; 450 let trait_ = self.resolver.resolve_known_trait(self.db, &path)?;
421 self.db.trait_data(trait_).associated_type_by_name(&name::OUTPUT_TYPE) 451 self.db.trait_data(trait_).associated_type_by_name(&name![Output])
422 } 452 }
423 453
424 fn resolve_boxed_box(&self) -> Option<AdtId> { 454 fn resolve_boxed_box(&self) -> Option<AdtId> {
425 let path = known::std_boxed_box(); 455 let path = path![std::boxed::Box];
426 let struct_ = self.resolver.resolve_known_struct(self.db, &path)?; 456 let struct_ = self.resolver.resolve_known_struct(self.db, &path)?;
427 Some(struct_.into()) 457 Some(struct_.into())
428 } 458 }
429 459
430 fn resolve_range_full(&self) -> Option<AdtId> { 460 fn resolve_range_full(&self) -> Option<AdtId> {
431 let path = known::std_ops_range_full(); 461 let path = path![std::ops::RangeFull];
432 let struct_ = self.resolver.resolve_known_struct(self.db, &path)?; 462 let struct_ = self.resolver.resolve_known_struct(self.db, &path)?;
433 Some(struct_.into()) 463 Some(struct_.into())
434 } 464 }
435 465
436 fn resolve_range(&self) -> Option<AdtId> { 466 fn resolve_range(&self) -> Option<AdtId> {
437 let path = known::std_ops_range(); 467 let path = path![std::ops::Range];
438 let struct_ = self.resolver.resolve_known_struct(self.db, &path)?; 468 let struct_ = self.resolver.resolve_known_struct(self.db, &path)?;
439 Some(struct_.into()) 469 Some(struct_.into())
440 } 470 }
441 471
442 fn resolve_range_inclusive(&self) -> Option<AdtId> { 472 fn resolve_range_inclusive(&self) -> Option<AdtId> {
443 let path = known::std_ops_range_inclusive(); 473 let path = path![std::ops::RangeInclusive];
444 let struct_ = self.resolver.resolve_known_struct(self.db, &path)?; 474 let struct_ = self.resolver.resolve_known_struct(self.db, &path)?;
445 Some(struct_.into()) 475 Some(struct_.into())
446 } 476 }
447 477
448 fn resolve_range_from(&self) -> Option<AdtId> { 478 fn resolve_range_from(&self) -> Option<AdtId> {
449 let path = known::std_ops_range_from(); 479 let path = path![std::ops::RangeFrom];
450 let struct_ = self.resolver.resolve_known_struct(self.db, &path)?; 480 let struct_ = self.resolver.resolve_known_struct(self.db, &path)?;
451 Some(struct_.into()) 481 Some(struct_.into())
452 } 482 }
453 483
454 fn resolve_range_to(&self) -> Option<AdtId> { 484 fn resolve_range_to(&self) -> Option<AdtId> {
455 let path = known::std_ops_range_to(); 485 let path = path![std::ops::RangeTo];
456 let struct_ = self.resolver.resolve_known_struct(self.db, &path)?; 486 let struct_ = self.resolver.resolve_known_struct(self.db, &path)?;
457 Some(struct_.into()) 487 Some(struct_.into())
458 } 488 }
459 489
460 fn resolve_range_to_inclusive(&self) -> Option<AdtId> { 490 fn resolve_range_to_inclusive(&self) -> Option<AdtId> {
461 let path = known::std_ops_range_to_inclusive(); 491 let path = path![std::ops::RangeToInclusive];
462 let struct_ = self.resolver.resolve_known_struct(self.db, &path)?; 492 let struct_ = self.resolver.resolve_known_struct(self.db, &path)?;
463 Some(struct_.into()) 493 Some(struct_.into())
464 } 494 }
diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs
index 2c296987c..2e3cdd53a 100644
--- a/crates/ra_hir_ty/src/infer/expr.rs
+++ b/crates/ra_hir_ty/src/infer/expr.rs
@@ -10,7 +10,7 @@ use hir_def::{
10 resolver::resolver_for_expr, 10 resolver::resolver_for_expr,
11 AdtId, ContainerId, Lookup, StructFieldId, 11 AdtId, ContainerId, Lookup, StructFieldId,
12}; 12};
13use hir_expand::name::{self, Name}; 13use hir_expand::name::{name, Name};
14use ra_syntax::ast::RangeOp; 14use ra_syntax::ast::RangeOp;
15 15
16use crate::{ 16use crate::{
@@ -19,8 +19,8 @@ use crate::{
19 method_resolution, op, 19 method_resolution, op,
20 traits::InEnvironment, 20 traits::InEnvironment,
21 utils::{generics, variant_data, Generics}, 21 utils::{generics, variant_data, Generics},
22 CallableDef, InferTy, IntTy, Mutability, Obligation, ProjectionPredicate, ProjectionTy, Substs, 22 ApplicationTy, CallableDef, InferTy, IntTy, Mutability, Obligation, Substs, TraitRef, Ty,
23 TraitRef, Ty, TypeCtor, TypeWalk, Uncertain, 23 TypeCtor, TypeWalk, Uncertain,
24}; 24};
25 25
26use super::{BindingMode, Expectation, InferenceContext, InferenceDiagnostic, TypeMismatch}; 26use super::{BindingMode, Expectation, InferenceContext, InferenceDiagnostic, TypeMismatch};
@@ -95,21 +95,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
95 Expr::For { iterable, body, pat } => { 95 Expr::For { iterable, body, pat } => {
96 let iterable_ty = self.infer_expr(*iterable, &Expectation::none()); 96 let iterable_ty = self.infer_expr(*iterable, &Expectation::none());
97 97
98 let pat_ty = match self.resolve_into_iter_item() { 98 let pat_ty =
99 Some(into_iter_item_alias) => { 99 self.resolve_associated_type(iterable_ty, self.resolve_into_iter_item());
100 let pat_ty = self.table.new_type_var();
101 let projection = ProjectionPredicate {
102 ty: pat_ty.clone(),
103 projection_ty: ProjectionTy {
104 associated_ty: into_iter_item_alias,
105 parameters: Substs::single(iterable_ty),
106 },
107 };
108 self.obligations.push(Obligation::Projection(projection));
109 self.resolve_ty_as_possible(pat_ty)
110 }
111 None => Ty::Unknown,
112 };
113 100
114 self.infer_pat(*pat, &pat_ty, BindingMode::default()); 101 self.infer_pat(*pat, &pat_ty, BindingMode::default());
115 self.infer_expr(*body, &Expectation::has_type(Ty::unit())); 102 self.infer_expr(*body, &Expectation::has_type(Ty::unit()));
@@ -284,40 +271,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
284 } 271 }
285 Expr::Await { expr } => { 272 Expr::Await { expr } => {
286 let inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); 273 let inner_ty = self.infer_expr_inner(*expr, &Expectation::none());
287 let ty = match self.resolve_future_future_output() { 274 let ty =
288 Some(future_future_output_alias) => { 275 self.resolve_associated_type(inner_ty, self.resolve_future_future_output());
289 let ty = self.table.new_type_var();
290 let projection = ProjectionPredicate {
291 ty: ty.clone(),
292 projection_ty: ProjectionTy {
293 associated_ty: future_future_output_alias,
294 parameters: Substs::single(inner_ty),
295 },
296 };
297 self.obligations.push(Obligation::Projection(projection));
298 self.resolve_ty_as_possible(ty)
299 }
300 None => Ty::Unknown,
301 };
302 ty 276 ty
303 } 277 }
304 Expr::Try { expr } => { 278 Expr::Try { expr } => {
305 let inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); 279 let inner_ty = self.infer_expr_inner(*expr, &Expectation::none());
306 let ty = match self.resolve_ops_try_ok() { 280 let ty = self.resolve_associated_type(inner_ty, self.resolve_ops_try_ok());
307 Some(ops_try_ok_alias) => {
308 let ty = self.table.new_type_var();
309 let projection = ProjectionPredicate {
310 ty: ty.clone(),
311 projection_ty: ProjectionTy {
312 associated_ty: ops_try_ok_alias,
313 parameters: Substs::single(inner_ty),
314 },
315 };
316 self.obligations.push(Obligation::Projection(projection));
317 self.resolve_ty_as_possible(ty)
318 }
319 None => Ty::Unknown,
320 };
321 ty 281 ty
322 } 282 }
323 Expr::Cast { expr, type_ref } => { 283 Expr::Cast { expr, type_ref } => {
@@ -372,31 +332,36 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
372 }, 332 },
373 UnaryOp::Neg => { 333 UnaryOp::Neg => {
374 match &inner_ty { 334 match &inner_ty {
375 Ty::Apply(a_ty) => match a_ty.ctor { 335 // Fast path for builtins
376 TypeCtor::Int(Uncertain::Unknown) 336 Ty::Apply(ApplicationTy {
377 | TypeCtor::Int(Uncertain::Known(IntTy { 337 ctor:
378 signedness: Signedness::Signed, 338 TypeCtor::Int(Uncertain::Known(IntTy {
379 .. 339 signedness: Signedness::Signed,
380 })) 340 ..
381 | TypeCtor::Float(..) => inner_ty, 341 })),
382 _ => Ty::Unknown, 342 ..
383 }, 343 })
384 Ty::Infer(InferTy::IntVar(..)) | Ty::Infer(InferTy::FloatVar(..)) => { 344 | Ty::Apply(ApplicationTy {
385 inner_ty 345 ctor: TypeCtor::Int(Uncertain::Unknown),
386 } 346 ..
387 // FIXME: resolve ops::Neg trait 347 })
388 _ => Ty::Unknown, 348 | Ty::Apply(ApplicationTy { ctor: TypeCtor::Float(_), .. })
349 | Ty::Infer(InferTy::IntVar(..))
350 | Ty::Infer(InferTy::FloatVar(..)) => inner_ty,
351 // Otherwise we resolve via the std::ops::Neg trait
352 _ => self
353 .resolve_associated_type(inner_ty, self.resolve_ops_neg_output()),
389 } 354 }
390 } 355 }
391 UnaryOp::Not => { 356 UnaryOp::Not => {
392 match &inner_ty { 357 match &inner_ty {
393 Ty::Apply(a_ty) => match a_ty.ctor { 358 // Fast path for builtins
394 TypeCtor::Bool | TypeCtor::Int(_) => inner_ty, 359 Ty::Apply(ApplicationTy { ctor: TypeCtor::Bool, .. })
395 _ => Ty::Unknown, 360 | Ty::Apply(ApplicationTy { ctor: TypeCtor::Int(_), .. })
396 }, 361 | Ty::Infer(InferTy::IntVar(..)) => inner_ty,
397 Ty::Infer(InferTy::IntVar(..)) => inner_ty, 362 // Otherwise we resolve via the std::ops::Not trait
398 // FIXME: resolve ops::Not trait for inner_ty 363 _ => self
399 _ => Ty::Unknown, 364 .resolve_associated_type(inner_ty, self.resolve_ops_not_output()),
400 } 365 }
401 } 366 }
402 } 367 }
@@ -666,7 +631,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
666 // Parent arguments are unknown, except for the receiver type 631 // Parent arguments are unknown, except for the receiver type
667 if let Some(parent_generics) = def_generics.as_ref().map(|p| p.iter_parent()) { 632 if let Some(parent_generics) = def_generics.as_ref().map(|p| p.iter_parent()) {
668 for (_id, param) in parent_generics { 633 for (_id, param) in parent_generics {
669 if param.name == name::SELF_TYPE { 634 if param.name == name![Self] {
670 substs.push(receiver_ty.clone()); 635 substs.push(receiver_ty.clone());
671 } else { 636 } else {
672 substs.push(Ty::Unknown); 637 substs.push(Ty::Unknown);
diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs
index 93c5f9a15..6139adb72 100644
--- a/crates/ra_hir_ty/src/tests/traits.rs
+++ b/crates/ra_hir_ty/src/tests/traits.rs
@@ -116,6 +116,70 @@ mod collections {
116} 116}
117 117
118#[test] 118#[test]
119fn infer_ops_neg() {
120 let (db, pos) = TestDB::with_position(
121 r#"
122//- /main.rs crate:main deps:std
123
124struct Bar;
125struct Foo;
126
127impl std::ops::Neg for Bar {
128 type Output = Foo;
129}
130
131fn test() {
132 let a = Bar;
133 let b = -a;
134 b<|>;
135}
136
137//- /std.rs crate:std
138
139#[prelude_import] use ops::*;
140mod ops {
141 pub trait Neg {
142 type Output;
143 }
144}
145"#,
146 );
147 assert_eq!("Foo", type_at_pos(&db, pos));
148}
149
150#[test]
151fn infer_ops_not() {
152 let (db, pos) = TestDB::with_position(
153 r#"
154//- /main.rs crate:main deps:std
155
156struct Bar;
157struct Foo;
158
159impl std::ops::Not for Bar {
160 type Output = Foo;
161}
162
163fn test() {
164 let a = Bar;
165 let b = !a;
166 b<|>;
167}
168
169//- /std.rs crate:std
170
171#[prelude_import] use ops::*;
172mod ops {
173 pub trait Not {
174 type Output;
175 }
176}
177"#,
178 );
179 assert_eq!("Foo", type_at_pos(&db, pos));
180}
181
182#[test]
119fn infer_from_bound_1() { 183fn infer_from_bound_1() {
120 assert_snapshot!( 184 assert_snapshot!(
121 infer(r#" 185 infer(r#"
diff --git a/crates/ra_hir_ty/src/traits/builtin.rs b/crates/ra_hir_ty/src/traits/builtin.rs
index 598fd81e3..cd587a338 100644
--- a/crates/ra_hir_ty/src/traits/builtin.rs
+++ b/crates/ra_hir_ty/src/traits/builtin.rs
@@ -1,7 +1,7 @@
1//! This module provides the built-in trait implementations, e.g. to make 1//! This module provides the built-in trait implementations, e.g. to make
2//! closures implement `Fn`. 2//! closures implement `Fn`.
3use hir_def::{expr::Expr, lang_item::LangItemTarget, TraitId, TypeAliasId}; 3use hir_def::{expr::Expr, lang_item::LangItemTarget, TraitId, TypeAliasId};
4use hir_expand::name; 4use hir_expand::name::name;
5use ra_db::CrateId; 5use ra_db::CrateId;
6 6
7use super::{AssocTyValue, Impl}; 7use super::{AssocTyValue, Impl};
@@ -79,7 +79,7 @@ fn closure_fn_trait_impl_datum(
79 // and don't want to return a valid value only to find out later that FnOnce 79 // and don't want to return a valid value only to find out later that FnOnce
80 // is broken 80 // is broken
81 let fn_once_trait = get_fn_trait(db, krate, super::FnTrait::FnOnce)?; 81 let fn_once_trait = get_fn_trait(db, krate, super::FnTrait::FnOnce)?;
82 let _output = db.trait_data(fn_once_trait).associated_type_by_name(&name::OUTPUT_TYPE)?; 82 let _output = db.trait_data(fn_once_trait).associated_type_by_name(&name![Output])?;
83 83
84 let num_args: u16 = match &db.body(data.def.into())[data.expr] { 84 let num_args: u16 = match &db.body(data.def.into())[data.expr] {
85 Expr::Lambda { args, .. } => args.len() as u16, 85 Expr::Lambda { args, .. } => args.len() as u16,
@@ -137,7 +137,7 @@ fn closure_fn_trait_output_assoc_ty_value(
137 137
138 let output_ty_id = db 138 let output_ty_id = db
139 .trait_data(fn_once_trait) 139 .trait_data(fn_once_trait)
140 .associated_type_by_name(&name::OUTPUT_TYPE) 140 .associated_type_by_name(&name![Output])
141 .expect("assoc ty value should not exist"); 141 .expect("assoc ty value should not exist");
142 142
143 BuiltinImplAssocTyValueData { 143 BuiltinImplAssocTyValueData {
diff --git a/crates/ra_hir_ty/src/utils.rs b/crates/ra_hir_ty/src/utils.rs
index aeb211a91..0049d3c6f 100644
--- a/crates/ra_hir_ty/src/utils.rs
+++ b/crates/ra_hir_ty/src/utils.rs
@@ -10,10 +10,8 @@ use hir_def::{
10 type_ref::TypeRef, 10 type_ref::TypeRef,
11 ContainerId, GenericDefId, Lookup, TraitId, TypeAliasId, TypeParamId, VariantId, 11 ContainerId, GenericDefId, Lookup, TraitId, TypeAliasId, TypeParamId, VariantId,
12}; 12};
13use hir_expand::name::{self, Name}; 13use hir_expand::name::{name, Name};
14 14
15// FIXME: this is wrong, b/c it can't express `trait T: PartialEq<()>`.
16// We should return a `TraitREf` here.
17fn direct_super_traits(db: &impl DefDatabase, trait_: TraitId) -> Vec<TraitId> { 15fn direct_super_traits(db: &impl DefDatabase, trait_: TraitId) -> Vec<TraitId> {
18 let resolver = trait_.resolver(db); 16 let resolver = trait_.resolver(db);
19 // returning the iterator directly doesn't easily work because of 17 // returning the iterator directly doesn't easily work because of
@@ -24,7 +22,7 @@ fn direct_super_traits(db: &impl DefDatabase, trait_: TraitId) -> Vec<TraitId> {
24 .where_predicates 22 .where_predicates
25 .iter() 23 .iter()
26 .filter_map(|pred| match &pred.type_ref { 24 .filter_map(|pred| match &pred.type_ref {
27 TypeRef::Path(p) if p.as_ident() == Some(&name::SELF_TYPE) => pred.bound.as_path(), 25 TypeRef::Path(p) if p.as_ident() == Some(&name![Self]) => pred.bound.as_path(),
28 _ => None, 26 _ => None,
29 }) 27 })
30 .filter_map(|path| match resolver.resolve_path_in_type_ns_fully(db, path) { 28 .filter_map(|path| match resolver.resolve_path_in_type_ns_fully(db, path) {
diff --git a/crates/ra_lsp_server/src/config.rs b/crates/ra_lsp_server/src/config.rs
index 8045f3d60..67942aa41 100644
--- a/crates/ra_lsp_server/src/config.rs
+++ b/crates/ra_lsp_server/src/config.rs
@@ -9,6 +9,7 @@
9 9
10use rustc_hash::FxHashMap; 10use rustc_hash::FxHashMap;
11 11
12use ra_project_model::CargoFeatures;
12use serde::{Deserialize, Deserializer}; 13use serde::{Deserialize, Deserializer};
13 14
14/// Client provided initialization options 15/// Client provided initialization options
@@ -37,6 +38,9 @@ pub struct ServerConfig {
37 38
38 /// Fine grained feature flags to disable specific features. 39 /// Fine grained feature flags to disable specific features.
39 pub feature_flags: FxHashMap<String, bool>, 40 pub feature_flags: FxHashMap<String, bool>,
41
42 /// Cargo feature configurations.
43 pub cargo_features: CargoFeatures,
40} 44}
41 45
42impl Default for ServerConfig { 46impl Default for ServerConfig {
@@ -49,6 +53,7 @@ impl Default for ServerConfig {
49 max_inlay_hint_length: None, 53 max_inlay_hint_length: None,
50 with_sysroot: true, 54 with_sysroot: true,
51 feature_flags: FxHashMap::default(), 55 feature_flags: FxHashMap::default(),
56 cargo_features: Default::default(),
52 } 57 }
53 } 58 }
54} 59}
diff --git a/crates/ra_lsp_server/src/conv.rs b/crates/ra_lsp_server/src/conv.rs
index b13093cfe..5561f6270 100644
--- a/crates/ra_lsp_server/src/conv.rs
+++ b/crates/ra_lsp_server/src/conv.rs
@@ -130,6 +130,11 @@ impl ConvWith<(&LineIndex, LineEndings)> for CompletionItem {
130 deprecated: Some(self.deprecated()), 130 deprecated: Some(self.deprecated()),
131 ..Default::default() 131 ..Default::default()
132 }; 132 };
133
134 if self.deprecated() {
135 res.tags = Some(vec![lsp_types::CompletionItemTag::Deprecated])
136 }
137
133 res.insert_text_format = Some(match self.insert_text_format() { 138 res.insert_text_format = Some(match self.insert_text_format() {
134 InsertTextFormat::Snippet => lsp_types::InsertTextFormat::Snippet, 139 InsertTextFormat::Snippet => lsp_types::InsertTextFormat::Snippet,
135 InsertTextFormat::PlainText => lsp_types::InsertTextFormat::PlainText, 140 InsertTextFormat::PlainText => lsp_types::InsertTextFormat::PlainText,
diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs
index 158cac0be..965e7c53c 100644
--- a/crates/ra_lsp_server/src/main_loop.rs
+++ b/crates/ra_lsp_server/src/main_loop.rs
@@ -67,6 +67,7 @@ pub fn main_loop(
67 let workspace = ra_project_model::ProjectWorkspace::discover_with_sysroot( 67 let workspace = ra_project_model::ProjectWorkspace::discover_with_sysroot(
68 ws_root.as_path(), 68 ws_root.as_path(),
69 config.with_sysroot, 69 config.with_sysroot,
70 &config.cargo_features,
70 ); 71 );
71 match workspace { 72 match workspace {
72 Ok(workspace) => loaded_workspaces.push(workspace), 73 Ok(workspace) => loaded_workspaces.push(workspace),
diff --git a/crates/ra_project_model/src/cargo_workspace.rs b/crates/ra_project_model/src/cargo_workspace.rs
index 351997dcd..4a0437da3 100644
--- a/crates/ra_project_model/src/cargo_workspace.rs
+++ b/crates/ra_project_model/src/cargo_workspace.rs
@@ -6,6 +6,7 @@ use cargo_metadata::{CargoOpt, MetadataCommand};
6use ra_arena::{impl_arena_id, Arena, RawId}; 6use ra_arena::{impl_arena_id, Arena, RawId};
7use ra_db::Edition; 7use ra_db::Edition;
8use rustc_hash::FxHashMap; 8use rustc_hash::FxHashMap;
9use serde::Deserialize;
9 10
10use crate::Result; 11use crate::Result;
11 12
@@ -23,6 +24,20 @@ pub struct CargoWorkspace {
23 pub(crate) workspace_root: PathBuf, 24 pub(crate) workspace_root: PathBuf,
24} 25}
25 26
27#[derive(Deserialize, Clone, Debug, PartialEq, Eq, Default)]
28#[serde(rename_all = "camelCase", default)]
29pub struct CargoFeatures {
30 /// Do not activate the `default` feature.
31 pub no_default_features: bool,
32
33 /// Activate all available features
34 pub all_features: bool,
35
36 /// List of features to activate.
37 /// This will be ignored if `cargo_all_features` is true.
38 pub features: Vec<String>,
39}
40
26#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] 41#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
27pub struct Package(RawId); 42pub struct Package(RawId);
28impl_arena_id!(Package); 43impl_arena_id!(Package);
@@ -132,9 +147,21 @@ impl Target {
132} 147}
133 148
134impl CargoWorkspace { 149impl CargoWorkspace {
135 pub fn from_cargo_metadata(cargo_toml: &Path) -> Result<CargoWorkspace> { 150 pub fn from_cargo_metadata(
151 cargo_toml: &Path,
152 cargo_features: &CargoFeatures,
153 ) -> Result<CargoWorkspace> {
136 let mut meta = MetadataCommand::new(); 154 let mut meta = MetadataCommand::new();
137 meta.manifest_path(cargo_toml).features(CargoOpt::AllFeatures); 155 meta.manifest_path(cargo_toml);
156 if cargo_features.all_features {
157 meta.features(CargoOpt::AllFeatures);
158 } else if cargo_features.no_default_features {
159 // FIXME: `NoDefaultFeatures` is mutual exclusive with `SomeFeatures`
160 // https://github.com/oli-obk/cargo_metadata/issues/79
161 meta.features(CargoOpt::NoDefaultFeatures);
162 } else {
163 meta.features(CargoOpt::SomeFeatures(cargo_features.features.clone()));
164 }
138 if let Some(parent) = cargo_toml.parent() { 165 if let Some(parent) = cargo_toml.parent() {
139 meta.current_dir(parent); 166 meta.current_dir(parent);
140 } 167 }
diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs
index 55ff4d6ef..d71b7031a 100644
--- a/crates/ra_project_model/src/lib.rs
+++ b/crates/ra_project_model/src/lib.rs
@@ -18,7 +18,7 @@ use rustc_hash::FxHashMap;
18use serde_json::from_reader; 18use serde_json::from_reader;
19 19
20pub use crate::{ 20pub use crate::{
21 cargo_workspace::{CargoWorkspace, Package, Target, TargetKind}, 21 cargo_workspace::{CargoFeatures, CargoWorkspace, Package, Target, TargetKind},
22 json_project::JsonProject, 22 json_project::JsonProject,
23 sysroot::Sysroot, 23 sysroot::Sysroot,
24}; 24};
@@ -60,11 +60,15 @@ impl PackageRoot {
60} 60}
61 61
62impl ProjectWorkspace { 62impl ProjectWorkspace {
63 pub fn discover(path: &Path) -> Result<ProjectWorkspace> { 63 pub fn discover(path: &Path, cargo_features: &CargoFeatures) -> Result<ProjectWorkspace> {
64 ProjectWorkspace::discover_with_sysroot(path, true) 64 ProjectWorkspace::discover_with_sysroot(path, true, cargo_features)
65 } 65 }
66 66
67 pub fn discover_with_sysroot(path: &Path, with_sysroot: bool) -> Result<ProjectWorkspace> { 67 pub fn discover_with_sysroot(
68 path: &Path,
69 with_sysroot: bool,
70 cargo_features: &CargoFeatures,
71 ) -> Result<ProjectWorkspace> {
68 match find_rust_project_json(path) { 72 match find_rust_project_json(path) {
69 Some(json_path) => { 73 Some(json_path) => {
70 let file = File::open(json_path)?; 74 let file = File::open(json_path)?;
@@ -73,7 +77,7 @@ impl ProjectWorkspace {
73 } 77 }
74 None => { 78 None => {
75 let cargo_toml = find_cargo_toml(path)?; 79 let cargo_toml = find_cargo_toml(path)?;
76 let cargo = CargoWorkspace::from_cargo_metadata(&cargo_toml)?; 80 let cargo = CargoWorkspace::from_cargo_metadata(&cargo_toml, cargo_features)?;
77 let sysroot = 81 let sysroot =
78 if with_sysroot { Sysroot::discover(&cargo_toml)? } else { Sysroot::default() }; 82 if with_sysroot { Sysroot::discover(&cargo_toml)? } else { Sysroot::default() };
79 Ok(ProjectWorkspace::Cargo { cargo, sysroot }) 83 Ok(ProjectWorkspace::Cargo { cargo, sysroot })