diff options
29 files changed, 494 insertions, 331 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 | ||
173 | fn has_new_fn(imp: &ast::ImplBlock) -> bool { | 168 | fn 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 | ||
23 | pub fn load_cargo(root: &Path) -> Result<(AnalysisHost, FxHashMap<SourceRootId, PackageRoot>)> { | 23 | pub 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 | }; |
18 | use hir_expand::{ | 18 | use hir_expand::{ |
19 | diagnostics::DiagnosticSink, | 19 | diagnostics::DiagnosticSink, |
20 | name::{self, AsName}, | 20 | name::{name, AsName}, |
21 | MacroDefId, | 21 | MacroDefId, |
22 | }; | 22 | }; |
23 | use hir_ty::{ | 23 | use 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 | ||
4 | use either::Either; | 4 | use either::Either; |
5 | use hir_expand::name::{self, AsName, Name}; | 5 | use hir_expand::name::{name, AsName, Name}; |
6 | use ra_arena::Arena; | 6 | use ra_arena::Arena; |
7 | use ra_syntax::{ | 7 | use 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 | ||
6 | use std::fmt; | 6 | use std::fmt; |
7 | 7 | ||
8 | use hir_expand::name::{self, Name}; | 8 | use hir_expand::name::{name, Name}; |
9 | 9 | ||
10 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] | 10 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] |
11 | pub enum Signedness { | 11 | pub enum Signedness { |
@@ -52,26 +52,26 @@ pub enum BuiltinType { | |||
52 | impl BuiltinType { | 52 | impl 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 @@ | |||
3 | use std::sync::Arc; | 3 | use std::sync::Arc; |
4 | 4 | ||
5 | use hir_expand::{ | 5 | use hir_expand::{ |
6 | name::{self, AsName, Name}, | 6 | name::{name, AsName, Name}, |
7 | AstId, | 7 | AstId, |
8 | }; | 8 | }; |
9 | use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner}; | 9 | use 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 | ||
7 | use either::Either; | 7 | use either::Either; |
8 | use hir_expand::{ | 8 | use hir_expand::{ |
9 | name::{self, AsName, Name}, | 9 | name::{name, AsName, Name}, |
10 | InFile, | 10 | InFile, |
11 | }; | 11 | }; |
12 | use ra_arena::{map::ArenaMap, Arena}; | 12 | use 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 @@ | |||
6 | use hir_expand::{ | 6 | use 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 | }; |
12 | use ra_cfg::CfgOptions; | 12 | use ra_cfg::CfgOptions; |
@@ -918,7 +918,7 @@ where | |||
918 | } | 918 | } |
919 | 919 | ||
920 | fn is_macro_rules(path: &Path) -> bool { | 920 | fn 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}; | |||
6 | use either::Either; | 6 | use either::Either; |
7 | use hir_expand::{ | 7 | use hir_expand::{ |
8 | hygiene::Hygiene, | 8 | hygiene::Hygiene, |
9 | name::{self, AsName, Name}, | 9 | name::{name, AsName, Name}, |
10 | }; | 10 | }; |
11 | use ra_db::CrateId; | 11 | use ra_db::CrateId; |
12 | use ra_syntax::{ | 12 | use 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 | ||
299 | pub mod known { | 296 | pub use hir_expand::name as __name; |
300 | use hir_expand::name; | 297 | |
301 | 298 | #[macro_export] | |
302 | use super::{Path, PathKind}; | 299 | macro_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]) | 319 | macro_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 | |||
328 | pub 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 @@ | |||
2 | use std::sync::Arc; | 2 | use std::sync::Arc; |
3 | 3 | ||
4 | use hir_expand::{ | 4 | use hir_expand::{ |
5 | name::{self, Name}, | 5 | name::{name, Name}, |
6 | MacroDefId, | 6 | MacroDefId, |
7 | }; | 7 | }; |
8 | use ra_db::CrateId; | 8 | use 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; | |||
12 | use crate::{name, quote, MacroCallId, MacroDefId, MacroDefKind}; | 12 | use crate::{name, quote, MacroCallId, MacroDefId, MacroDefKind}; |
13 | 13 | ||
14 | macro_rules! register_builtin { | 14 | macro_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 | ||
46 | register_builtin! { | 46 | register_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 | ||
58 | struct BasicAdtInfo { | 58 | struct 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 | ||
46 | register_builtin! { | 46 | register_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 | ||
58 | fn to_line_number(db: &dyn AstDatabase, file: HirFileId, pos: TextUnit) -> usize { | 58 | fn 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 | 107 | pub mod known { |
108 | pub const ISIZE: Name = Name::new_inline_ascii(b"isize"); | 108 | macro_rules! known_names { |
109 | pub const I8: Name = Name::new_inline_ascii(b"i8"); | 109 | ($($ident:ident),* $(,)?) => { |
110 | pub const I16: Name = Name::new_inline_ascii(b"i16"); | 110 | $( |
111 | pub const I32: Name = Name::new_inline_ascii(b"i32"); | 111 | #[allow(bad_style)] |
112 | pub const I64: Name = Name::new_inline_ascii(b"i64"); | 112 | pub const $ident: super::Name = |
113 | pub const I128: Name = Name::new_inline_ascii(b"i128"); | 113 | super::Name::new_inline_ascii(stringify!($ident).as_bytes()); |
114 | pub const USIZE: Name = Name::new_inline_ascii(b"usize"); | 114 | )* |
115 | pub const U8: Name = Name::new_inline_ascii(b"u8"); | 115 | }; |
116 | pub const U16: Name = Name::new_inline_ascii(b"u16"); | 116 | } |
117 | pub const U32: Name = Name::new_inline_ascii(b"u32"); | 117 | |
118 | pub const U64: Name = Name::new_inline_ascii(b"u64"); | 118 | known_names!( |
119 | pub const U128: Name = Name::new_inline_ascii(b"u128"); | 119 | // Primitives |
120 | pub const F32: Name = Name::new_inline_ascii(b"f32"); | 120 | isize, |
121 | pub const F64: Name = Name::new_inline_ascii(b"f64"); | 121 | i8, |
122 | pub const BOOL: Name = Name::new_inline_ascii(b"bool"); | 122 | i16, |
123 | pub const CHAR: Name = Name::new_inline_ascii(b"char"); | 123 | i32, |
124 | pub const STR: Name = Name::new_inline_ascii(b"str"); | 124 | i64, |
125 | 125 | i128, | |
126 | // Special names | 126 | usize, |
127 | pub const SELF_PARAM: Name = Name::new_inline_ascii(b"self"); | 127 | u8, |
128 | pub const SELF_TYPE: Name = Name::new_inline_ascii(b"Self"); | 128 | u16, |
129 | pub 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, |
132 | pub const STD: Name = Name::new_inline_ascii(b"std"); | 132 | f32, |
133 | pub const ITER: Name = Name::new_inline_ascii(b"iter"); | 133 | f64, |
134 | pub const OPS: Name = Name::new_inline_ascii(b"ops"); | 134 | bool, |
135 | pub const FUTURE: Name = Name::new_inline_ascii(b"future"); | 135 | char, |
136 | pub const RESULT: Name = Name::new_inline_ascii(b"result"); | 136 | str, |
137 | pub 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) |
140 | pub const INTO_ITERATOR_TYPE: Name = Name::new_inline_ascii(b"IntoIterator"); | 140 | std, |
141 | pub const ITEM_TYPE: Name = Name::new_inline_ascii(b"Item"); | 141 | iter, |
142 | pub const TRY_TYPE: Name = Name::new_inline_ascii(b"Try"); | 142 | ops, |
143 | pub const OK_TYPE: Name = Name::new_inline_ascii(b"Ok"); | 143 | future, |
144 | pub const FUTURE_TYPE: Name = Name::new_inline_ascii(b"Future"); | 144 | result, |
145 | pub const RESULT_TYPE: Name = Name::new_inline_ascii(b"Result"); | 145 | boxed, |
146 | pub const OUTPUT_TYPE: Name = Name::new_inline_ascii(b"Output"); | 146 | // Components of known path (type name) |
147 | pub const TARGET_TYPE: Name = Name::new_inline_ascii(b"Target"); | 147 | IntoIterator, |
148 | pub const BOX_TYPE: Name = Name::new_inline_ascii(b"Box"); | 148 | Item, |
149 | pub const RANGE_FROM_TYPE: Name = Name::new_inline_ascii(b"RangeFrom"); | 149 | Try, |
150 | pub const RANGE_FULL_TYPE: Name = Name::new_inline_ascii(b"RangeFull"); | 150 | Ok, |
151 | pub const RANGE_INCLUSIVE_TYPE: Name = Name::new_inline_ascii(b"RangeInclusive"); | 151 | Future, |
152 | pub const RANGE_TO_INCLUSIVE_TYPE: Name = Name::new_inline_ascii(b"RangeToInclusive"); | 152 | Result, |
153 | pub const RANGE_TO_TYPE: Name = Name::new_inline_ascii(b"RangeTo"); | 153 | Output, |
154 | pub const RANGE_TYPE: Name = Name::new_inline_ascii(b"Range"); | 154 | Target, |
155 | 155 | Box, | |
156 | // Builtin Macros | 156 | RangeFrom, |
157 | pub const FILE_MACRO: Name = Name::new_inline_ascii(b"file"); | 157 | RangeFull, |
158 | pub const COLUMN_MACRO: Name = Name::new_inline_ascii(b"column"); | 158 | RangeInclusive, |
159 | pub const COMPILE_ERROR_MACRO: Name = Name::new_inline_ascii(b"compile_error"); | 159 | RangeToInclusive, |
160 | pub const LINE_MACRO: Name = Name::new_inline_ascii(b"line"); | 160 | RangeTo, |
161 | pub const STRINGIFY_MACRO: Name = Name::new_inline_ascii(b"stringify"); | 161 | Range, |
162 | pub const FORMAT_ARGS_MACRO: Name = Name::new_inline_ascii(b"format_args"); | 162 | Neg, |
163 | pub 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, |
166 | pub const COPY_TRAIT: Name = Name::new_inline_ascii(b"Copy"); | 166 | column, |
167 | pub const CLONE_TRAIT: Name = Name::new_inline_ascii(b"Clone"); | 167 | compile_error, |
168 | pub const DEFAULT_TRAIT: Name = Name::new_inline_ascii(b"Default"); | 168 | line, |
169 | pub const DEBUG_TRAIT: Name = Name::new_inline_ascii(b"Debug"); | 169 | stringify, |
170 | pub const HASH_TRAIT: Name = Name::new_inline_ascii(b"Hash"); | 170 | format_args, |
171 | pub const ORD_TRAIT: Name = Name::new_inline_ascii(b"Ord"); | 171 | format_args_nl, |
172 | pub const PARTIAL_ORD_TRAIT: Name = Name::new_inline_ascii(b"PartialOrd"); | 172 | // Builtin derives |
173 | pub const EQ_TRAIT: Name = Name::new_inline_ascii(b"Eq"); | 173 | Copy, |
174 | pub 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 | |||
202 | pub 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 @@ | |||
6 | use std::iter::successors; | 6 | use std::iter::successors; |
7 | 7 | ||
8 | use hir_def::lang_item::LangItemTarget; | 8 | use hir_def::lang_item::LangItemTarget; |
9 | use hir_expand::name; | 9 | use hir_expand::name::name; |
10 | use log::{info, warn}; | 10 | use log::{info, warn}; |
11 | use ra_db::CrateId; | 11 | use 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 @@ | |||
3 | use std::sync::Arc; | 3 | use std::sync::Arc; |
4 | 4 | ||
5 | use hir_def::{ | 5 | use 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 | }; |
32 | use hir_expand::{diagnostics::DiagnosticSink, name}; | 32 | use hir_expand::{diagnostics::DiagnosticSink, name::name}; |
33 | use ra_arena::map::ArenaMap; | 33 | use ra_arena::map::ArenaMap; |
34 | use ra_prof::profile; | 34 | use ra_prof::profile; |
35 | 35 | ||
36 | use super::{ | 36 | use 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 | }; |
42 | use crate::{db::HirDatabase, infer::diagnostics::InferenceDiagnostic}; | 42 | use 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 | }; |
13 | use hir_expand::name::{self, Name}; | 13 | use hir_expand::name::{name, Name}; |
14 | use ra_syntax::ast::RangeOp; | 14 | use ra_syntax::ast::RangeOp; |
15 | 15 | ||
16 | use crate::{ | 16 | use 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 | ||
26 | use super::{BindingMode, Expectation, InferenceContext, InferenceDiagnostic, TypeMismatch}; | 26 | use 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] |
119 | fn infer_ops_neg() { | ||
120 | let (db, pos) = TestDB::with_position( | ||
121 | r#" | ||
122 | //- /main.rs crate:main deps:std | ||
123 | |||
124 | struct Bar; | ||
125 | struct Foo; | ||
126 | |||
127 | impl std::ops::Neg for Bar { | ||
128 | type Output = Foo; | ||
129 | } | ||
130 | |||
131 | fn test() { | ||
132 | let a = Bar; | ||
133 | let b = -a; | ||
134 | b<|>; | ||
135 | } | ||
136 | |||
137 | //- /std.rs crate:std | ||
138 | |||
139 | #[prelude_import] use ops::*; | ||
140 | mod 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] | ||
151 | fn infer_ops_not() { | ||
152 | let (db, pos) = TestDB::with_position( | ||
153 | r#" | ||
154 | //- /main.rs crate:main deps:std | ||
155 | |||
156 | struct Bar; | ||
157 | struct Foo; | ||
158 | |||
159 | impl std::ops::Not for Bar { | ||
160 | type Output = Foo; | ||
161 | } | ||
162 | |||
163 | fn test() { | ||
164 | let a = Bar; | ||
165 | let b = !a; | ||
166 | b<|>; | ||
167 | } | ||
168 | |||
169 | //- /std.rs crate:std | ||
170 | |||
171 | #[prelude_import] use ops::*; | ||
172 | mod 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] | ||
119 | fn infer_from_bound_1() { | 183 | fn 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`. |
3 | use hir_def::{expr::Expr, lang_item::LangItemTarget, TraitId, TypeAliasId}; | 3 | use hir_def::{expr::Expr, lang_item::LangItemTarget, TraitId, TypeAliasId}; |
4 | use hir_expand::name; | 4 | use hir_expand::name::name; |
5 | use ra_db::CrateId; | 5 | use ra_db::CrateId; |
6 | 6 | ||
7 | use super::{AssocTyValue, Impl}; | 7 | use 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 | }; |
13 | use hir_expand::name::{self, Name}; | 13 | use 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. | ||
17 | fn direct_super_traits(db: &impl DefDatabase, trait_: TraitId) -> Vec<TraitId> { | 15 | fn 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 | ||
10 | use rustc_hash::FxHashMap; | 10 | use rustc_hash::FxHashMap; |
11 | 11 | ||
12 | use ra_project_model::CargoFeatures; | ||
12 | use serde::{Deserialize, Deserializer}; | 13 | use 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 | ||
42 | impl Default for ServerConfig { | 46 | impl 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}; | |||
6 | use ra_arena::{impl_arena_id, Arena, RawId}; | 6 | use ra_arena::{impl_arena_id, Arena, RawId}; |
7 | use ra_db::Edition; | 7 | use ra_db::Edition; |
8 | use rustc_hash::FxHashMap; | 8 | use rustc_hash::FxHashMap; |
9 | use serde::Deserialize; | ||
9 | 10 | ||
10 | use crate::Result; | 11 | use 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)] | ||
29 | pub 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)] |
27 | pub struct Package(RawId); | 42 | pub struct Package(RawId); |
28 | impl_arena_id!(Package); | 43 | impl_arena_id!(Package); |
@@ -132,9 +147,21 @@ impl Target { | |||
132 | } | 147 | } |
133 | 148 | ||
134 | impl CargoWorkspace { | 149 | impl 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; | |||
18 | use serde_json::from_reader; | 18 | use serde_json::from_reader; |
19 | 19 | ||
20 | pub use crate::{ | 20 | pub 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 | ||
62 | impl ProjectWorkspace { | 62 | impl 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 }) |
diff --git a/editors/code/package.json b/editors/code/package.json index 7bc08ec31..e3bb07be7 100644 --- a/editors/code/package.json +++ b/editors/code/package.json | |||
@@ -278,6 +278,21 @@ | |||
278 | "type": "number", | 278 | "type": "number", |
279 | "default": 20, | 279 | "default": 20, |
280 | "description": "Maximum length for inlay hints" | 280 | "description": "Maximum length for inlay hints" |
281 | }, | ||
282 | "rust-analyzer.cargoFeatures.noDefaultFeatures": { | ||
283 | "type": "boolean", | ||
284 | "default": false, | ||
285 | "description": "Do not activate the `default` feature" | ||
286 | }, | ||
287 | "rust-analyzer.cargoFeatures.allFeatures": { | ||
288 | "type": "boolean", | ||
289 | "default": true, | ||
290 | "description": "Activate all available features" | ||
291 | }, | ||
292 | "rust-analyzer.cargoFeatures.features": { | ||
293 | "type": "array", | ||
294 | "default": [], | ||
295 | "description": "List of features to activate" | ||
281 | } | 296 | } |
282 | } | 297 | } |
283 | }, | 298 | }, |
diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts index 2d3b6a54e..defdfeb9c 100644 --- a/editors/code/src/config.ts +++ b/editors/code/src/config.ts | |||
@@ -15,6 +15,12 @@ export interface CargoWatchOptions { | |||
15 | ignore: string[]; | 15 | ignore: string[]; |
16 | } | 16 | } |
17 | 17 | ||
18 | export interface CargoFeatures { | ||
19 | noDefaultFeatures: boolean; | ||
20 | allFeatures: boolean; | ||
21 | features: string[]; | ||
22 | } | ||
23 | |||
18 | export class Config { | 24 | export class Config { |
19 | public highlightingOn = true; | 25 | public highlightingOn = true; |
20 | public rainbowHighlightingOn = false; | 26 | public rainbowHighlightingOn = false; |
@@ -35,8 +41,14 @@ export class Config { | |||
35 | command: '', | 41 | command: '', |
36 | ignore: [], | 42 | ignore: [], |
37 | }; | 43 | }; |
44 | public cargoFeatures: CargoFeatures = { | ||
45 | noDefaultFeatures: false, | ||
46 | allFeatures: true, | ||
47 | features: [], | ||
48 | }; | ||
38 | 49 | ||
39 | private prevEnhancedTyping: null | boolean = null; | 50 | private prevEnhancedTyping: null | boolean = null; |
51 | private prevCargoFeatures: null | CargoFeatures = null; | ||
40 | 52 | ||
41 | constructor() { | 53 | constructor() { |
42 | vscode.workspace.onDidChangeConfiguration(_ => | 54 | vscode.workspace.onDidChangeConfiguration(_ => |
@@ -47,6 +59,8 @@ export class Config { | |||
47 | 59 | ||
48 | public userConfigChanged() { | 60 | public userConfigChanged() { |
49 | const config = vscode.workspace.getConfiguration('rust-analyzer'); | 61 | const config = vscode.workspace.getConfiguration('rust-analyzer'); |
62 | let requireReloadMessage = null; | ||
63 | |||
50 | if (config.has('highlightingOn')) { | 64 | if (config.has('highlightingOn')) { |
51 | this.highlightingOn = config.get('highlightingOn') as boolean; | 65 | this.highlightingOn = config.get('highlightingOn') as boolean; |
52 | } | 66 | } |
@@ -74,19 +88,8 @@ export class Config { | |||
74 | } | 88 | } |
75 | 89 | ||
76 | if (this.prevEnhancedTyping !== this.enableEnhancedTyping) { | 90 | if (this.prevEnhancedTyping !== this.enableEnhancedTyping) { |
77 | const reloadAction = 'Reload now'; | 91 | requireReloadMessage = |
78 | vscode.window | 92 | 'Changing enhanced typing setting requires a reload'; |
79 | .showInformationMessage( | ||
80 | 'Changing enhanced typing setting requires a reload', | ||
81 | reloadAction, | ||
82 | ) | ||
83 | .then(selectedAction => { | ||
84 | if (selectedAction === reloadAction) { | ||
85 | vscode.commands.executeCommand( | ||
86 | 'workbench.action.reloadWindow', | ||
87 | ); | ||
88 | } | ||
89 | }); | ||
90 | this.prevEnhancedTyping = this.enableEnhancedTyping; | 93 | this.prevEnhancedTyping = this.enableEnhancedTyping; |
91 | } | 94 | } |
92 | 95 | ||
@@ -153,5 +156,53 @@ export class Config { | |||
153 | if (config.has('withSysroot')) { | 156 | if (config.has('withSysroot')) { |
154 | this.withSysroot = config.get('withSysroot') || false; | 157 | this.withSysroot = config.get('withSysroot') || false; |
155 | } | 158 | } |
159 | |||
160 | if (config.has('cargoFeatures.noDefaultFeatures')) { | ||
161 | this.cargoFeatures.noDefaultFeatures = config.get( | ||
162 | 'cargoFeatures.noDefaultFeatures', | ||
163 | false, | ||
164 | ); | ||
165 | } | ||
166 | if (config.has('cargoFeatures.allFeatures')) { | ||
167 | this.cargoFeatures.allFeatures = config.get( | ||
168 | 'cargoFeatures.allFeatures', | ||
169 | true, | ||
170 | ); | ||
171 | } | ||
172 | if (config.has('cargoFeatures.features')) { | ||
173 | this.cargoFeatures.features = config.get( | ||
174 | 'cargoFeatures.features', | ||
175 | [], | ||
176 | ); | ||
177 | } | ||
178 | |||
179 | if ( | ||
180 | this.prevCargoFeatures !== null && | ||
181 | (this.cargoFeatures.allFeatures !== | ||
182 | this.prevCargoFeatures.allFeatures || | ||
183 | this.cargoFeatures.noDefaultFeatures !== | ||
184 | this.prevCargoFeatures.noDefaultFeatures || | ||
185 | this.cargoFeatures.features.length !== | ||
186 | this.prevCargoFeatures.features.length || | ||
187 | this.cargoFeatures.features.some( | ||
188 | (v, i) => v !== this.prevCargoFeatures!.features[i], | ||
189 | )) | ||
190 | ) { | ||
191 | requireReloadMessage = 'Changing cargo features requires a reload'; | ||
192 | } | ||
193 | this.prevCargoFeatures = { ...this.cargoFeatures }; | ||
194 | |||
195 | if (requireReloadMessage !== null) { | ||
196 | const reloadAction = 'Reload now'; | ||
197 | vscode.window | ||
198 | .showInformationMessage(requireReloadMessage, reloadAction) | ||
199 | .then(selectedAction => { | ||
200 | if (selectedAction === reloadAction) { | ||
201 | vscode.commands.executeCommand( | ||
202 | 'workbench.action.reloadWindow', | ||
203 | ); | ||
204 | } | ||
205 | }); | ||
206 | } | ||
156 | } | 207 | } |
157 | } | 208 | } |
diff --git a/editors/code/src/server.ts b/editors/code/src/server.ts index 2fe45f1ed..5ace1d0fa 100644 --- a/editors/code/src/server.ts +++ b/editors/code/src/server.ts | |||
@@ -59,6 +59,7 @@ export class Server { | |||
59 | useClientWatching: Server.config.useClientWatching, | 59 | useClientWatching: Server.config.useClientWatching, |
60 | featureFlags: Server.config.featureFlags, | 60 | featureFlags: Server.config.featureFlags, |
61 | withSysroot: Server.config.withSysroot, | 61 | withSysroot: Server.config.withSysroot, |
62 | cargoFeatures: Server.config.cargoFeatures, | ||
62 | }, | 63 | }, |
63 | traceOutputChannel, | 64 | traceOutputChannel, |
64 | }; | 65 | }; |