aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2019-10-08 12:46:14 +0100
committerGitHub <[email protected]>2019-10-08 12:46:14 +0100
commit92cf0eba93b8d2705ed39bef1a4ea665ed3c25dc (patch)
treea015a8a8162acacb61b3353b4642c93cd80e51ae /crates
parent93199002af05f3a3dfd274fe10633372f2471b73 (diff)
parentb043358be936b7f139efd49b7d187d64e319830e (diff)
Merge #1924
1924: Support inferring&completing `Self` type in enum/struct/union definitions r=ice1000 a=ice1000 Signed-off-by: ice1000 <[email protected]> An attempt to fix #1908. This code works, but I believe the implementation is ugly. Please give me suggestions! Co-authored-by: ice1000 <[email protected]>
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_hir/src/code_model.rs4
-rw-r--r--crates/ra_hir/src/resolve.rs32
-rw-r--r--crates/ra_hir/src/source_binder.rs2
-rw-r--r--crates/ra_hir/src/ty/infer.rs1
-rw-r--r--crates/ra_hir/src/ty/lower.rs1
-rw-r--r--crates/ra_hir/src/ty/tests.rs19
-rw-r--r--crates/ra_ide_api/src/completion/complete_scope.rs29
-rw-r--r--crates/ra_ide_api/src/completion/presentation.rs2
8 files changed, 81 insertions, 9 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index e3a7e8e3c..58db6832d 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -24,7 +24,7 @@ use crate::{
24 U8, USIZE, 24 U8, USIZE,
25 }, 25 },
26 nameres::{CrateModuleId, ImportId, ModuleScope, Namespace}, 26 nameres::{CrateModuleId, ImportId, ModuleScope, Namespace},
27 resolve::{Resolver, TypeNs}, 27 resolve::{Resolver, Scope, TypeNs},
28 traits::TraitData, 28 traits::TraitData,
29 ty::{ 29 ty::{
30 primitive::{FloatBitness, FloatTy, IntBitness, IntTy, Signedness}, 30 primitive::{FloatBitness, FloatTy, IntBitness, IntTy, Signedness},
@@ -465,7 +465,7 @@ impl Enum {
465 // ...and add generic params, if present 465 // ...and add generic params, if present
466 let p = self.generic_params(db); 466 let p = self.generic_params(db);
467 let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r }; 467 let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r };
468 r 468 r.push_scope(Scope::AdtScope(self.into()))
469 } 469 }
470} 470}
471 471
diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs
index 39f8e1d8a..3c797c0c3 100644
--- a/crates/ra_hir/src/resolve.rs
+++ b/crates/ra_hir/src/resolve.rs
@@ -43,8 +43,10 @@ pub(crate) enum Scope {
43 ModuleScope(ModuleItemMap), 43 ModuleScope(ModuleItemMap),
44 /// Brings the generic parameters of an item into scope 44 /// Brings the generic parameters of an item into scope
45 GenericParams(Arc<GenericParams>), 45 GenericParams(Arc<GenericParams>),
46 /// Brings `Self` into scope 46 /// Brings `Self` in `impl` block into scope
47 ImplBlockScope(ImplBlock), 47 ImplBlockScope(ImplBlock),
48 /// Brings `Self` in enum, struct and union definitions into scope
49 AdtScope(Adt),
48 /// Local bindings 50 /// Local bindings
49 ExprScope(ExprScope), 51 ExprScope(ExprScope),
50} 52}
@@ -54,6 +56,7 @@ pub enum TypeNs {
54 SelfType(ImplBlock), 56 SelfType(ImplBlock),
55 GenericParam(u32), 57 GenericParam(u32),
56 Adt(Adt), 58 Adt(Adt),
59 AdtSelfType(Adt),
57 EnumVariant(EnumVariant), 60 EnumVariant(EnumVariant),
58 TypeAlias(TypeAlias), 61 TypeAlias(TypeAlias),
59 BuiltinType(BuiltinType), 62 BuiltinType(BuiltinType),
@@ -151,6 +154,12 @@ impl Resolver {
151 return Some((TypeNs::SelfType(*impl_), idx)); 154 return Some((TypeNs::SelfType(*impl_), idx));
152 } 155 }
153 } 156 }
157 Scope::AdtScope(adt) => {
158 if first_name == &SELF_TYPE {
159 let idx = if path.segments.len() == 1 { None } else { Some(1) };
160 return Some((TypeNs::AdtSelfType(*adt), idx));
161 }
162 }
154 Scope::ModuleScope(m) => { 163 Scope::ModuleScope(m) => {
155 let (module_def, idx) = m.crate_def_map.resolve_path(db, m.module_id, path); 164 let (module_def, idx) = m.crate_def_map.resolve_path(db, m.module_id, path);
156 let res = match module_def.take_types()? { 165 let res = match module_def.take_types()? {
@@ -200,7 +209,10 @@ impl Resolver {
200 let skip_to_mod = path.kind != PathKind::Plain && !path.is_self(); 209 let skip_to_mod = path.kind != PathKind::Plain && !path.is_self();
201 for scope in self.scopes.iter().rev() { 210 for scope in self.scopes.iter().rev() {
202 match scope { 211 match scope {
203 Scope::ExprScope(_) | Scope::GenericParams(_) | Scope::ImplBlockScope(_) 212 Scope::AdtScope(_)
213 | Scope::ExprScope(_)
214 | Scope::GenericParams(_)
215 | Scope::ImplBlockScope(_)
204 if skip_to_mod => 216 if skip_to_mod =>
205 { 217 {
206 continue 218 continue
@@ -233,7 +245,13 @@ impl Resolver {
233 return Some(ResolveValueResult::Partial(ty, 1)); 245 return Some(ResolveValueResult::Partial(ty, 1));
234 } 246 }
235 } 247 }
236 Scope::ImplBlockScope(_) => continue, 248 Scope::AdtScope(adt) if n_segments > 1 => {
249 if first_name == &SELF_TYPE {
250 let ty = TypeNs::AdtSelfType(*adt);
251 return Some(ResolveValueResult::Partial(ty, 1));
252 }
253 }
254 Scope::ImplBlockScope(_) | Scope::AdtScope(_) => continue,
237 255
238 Scope::ModuleScope(m) => { 256 Scope::ModuleScope(m) => {
239 let (module_def, idx) = m.crate_def_map.resolve_path(db, m.module_id, path); 257 let (module_def, idx) = m.crate_def_map.resolve_path(db, m.module_id, path);
@@ -389,7 +407,8 @@ pub enum ScopeDef {
389 ModuleDef(ModuleDef), 407 ModuleDef(ModuleDef),
390 MacroDef(MacroDef), 408 MacroDef(MacroDef),
391 GenericParam(u32), 409 GenericParam(u32),
392 SelfType(ImplBlock), 410 ImplSelfType(ImplBlock),
411 AdtSelfType(Adt),
393 LocalBinding(PatId), 412 LocalBinding(PatId),
394 Unknown, 413 Unknown,
395} 414}
@@ -437,7 +456,10 @@ impl Scope {
437 } 456 }
438 } 457 }
439 Scope::ImplBlockScope(i) => { 458 Scope::ImplBlockScope(i) => {
440 f(SELF_TYPE, ScopeDef::SelfType(*i)); 459 f(SELF_TYPE, ScopeDef::ImplSelfType(*i));
460 }
461 Scope::AdtScope(i) => {
462 f(SELF_TYPE, ScopeDef::AdtSelfType(*i));
441 } 463 }
442 Scope::ExprScope(e) => { 464 Scope::ExprScope(e) => {
443 e.expr_scopes.entries(e.scope_id).iter().for_each(|e| { 465 e.expr_scopes.entries(e.scope_id).iter().for_each(|e| {
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index 088335e66..a907d6a9f 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -216,7 +216,7 @@ impl SourceAnalyzer {
216 let types = self.resolver.resolve_path_in_type_ns_fully(db, &path).map(|ty| match ty { 216 let types = self.resolver.resolve_path_in_type_ns_fully(db, &path).map(|ty| match ty {
217 TypeNs::SelfType(it) => PathResolution::SelfType(it), 217 TypeNs::SelfType(it) => PathResolution::SelfType(it),
218 TypeNs::GenericParam(it) => PathResolution::GenericParam(it), 218 TypeNs::GenericParam(it) => PathResolution::GenericParam(it),
219 TypeNs::Adt(it) => PathResolution::Def(it.into()), 219 TypeNs::AdtSelfType(it) | TypeNs::Adt(it) => PathResolution::Def(it.into()),
220 TypeNs::EnumVariant(it) => PathResolution::Def(it.into()), 220 TypeNs::EnumVariant(it) => PathResolution::Def(it.into()),
221 TypeNs::TypeAlias(it) => PathResolution::Def(it.into()), 221 TypeNs::TypeAlias(it) => PathResolution::Def(it.into()),
222 TypeNs::BuiltinType(it) => PathResolution::Def(it.into()), 222 TypeNs::BuiltinType(it) => PathResolution::Def(it.into()),
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index ca9aefc42..a69f04ff1 100644
--- a/crates/ra_hir/src/ty/infer.rs
+++ b/crates/ra_hir/src/ty/infer.rs
@@ -559,6 +559,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
559 match resolver.resolve_path_in_type_ns_fully(self.db, &path) { 559 match resolver.resolve_path_in_type_ns_fully(self.db, &path) {
560 Some(TypeNs::Adt(Adt::Struct(it))) => it.into(), 560 Some(TypeNs::Adt(Adt::Struct(it))) => it.into(),
561 Some(TypeNs::Adt(Adt::Union(it))) => it.into(), 561 Some(TypeNs::Adt(Adt::Union(it))) => it.into(),
562 Some(TypeNs::AdtSelfType(adt)) => adt.into(),
562 Some(TypeNs::EnumVariant(it)) => it.into(), 563 Some(TypeNs::EnumVariant(it)) => it.into(),
563 Some(TypeNs::TypeAlias(it)) => it.into(), 564 Some(TypeNs::TypeAlias(it)) => it.into(),
564 565
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs
index 4b67c82e7..a604c02e2 100644
--- a/crates/ra_hir/src/ty/lower.rs
+++ b/crates/ra_hir/src/ty/lower.rs
@@ -175,6 +175,7 @@ impl Ty {
175 Ty::Param { idx, name } 175 Ty::Param { idx, name }
176 } 176 }
177 TypeNs::SelfType(impl_block) => impl_block.target_ty(db), 177 TypeNs::SelfType(impl_block) => impl_block.target_ty(db),
178 TypeNs::AdtSelfType(adt) => adt.ty(db),
178 179
179 TypeNs::Adt(it) => Ty::from_hir_path_inner(db, resolver, resolved_segment, it.into()), 180 TypeNs::Adt(it) => Ty::from_hir_path_inner(db, resolver, resolved_segment, it.into()),
180 TypeNs::BuiltinType(it) => { 181 TypeNs::BuiltinType(it) => {
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index 25dad81eb..03b30adcd 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -135,6 +135,25 @@ mod boxed {
135} 135}
136 136
137#[test] 137#[test]
138fn infer_adt_self() {
139 let (db, pos) = MockDatabase::with_position(
140 r#"
141//- /main.rs
142enum Nat { Succ(Self), Demo(Nat), Zero }
143
144fn test() {
145 let foo: Nat = Nat::Zero;
146 if let Nat::Succ(x) = foo {
147 x<|>
148 }
149}
150
151"#,
152 );
153 assert_eq!("Nat", type_at_pos(&db, pos));
154}
155
156#[test]
138fn infer_try() { 157fn infer_try() {
139 let (mut db, pos) = MockDatabase::with_position( 158 let (mut db, pos) = MockDatabase::with_position(
140 r#" 159 r#"
diff --git a/crates/ra_ide_api/src/completion/complete_scope.rs b/crates/ra_ide_api/src/completion/complete_scope.rs
index 515a6285c..38a6c3d37 100644
--- a/crates/ra_ide_api/src/completion/complete_scope.rs
+++ b/crates/ra_ide_api/src/completion/complete_scope.rs
@@ -310,6 +310,35 @@ mod tests {
310 } 310 }
311 311
312 #[test] 312 #[test]
313 fn completes_self_in_enum() {
314 assert_debug_snapshot!(
315 do_reference_completion(
316 r"
317 enum X {
318 Y(<|>)
319 }
320 "
321 ),
322 @r###"[
323 CompletionItem {
324 label: "Self",
325 source_range: [48; 48),
326 delete: [48; 48),
327 insert: "Self",
328 kind: TypeParam,
329 },
330 CompletionItem {
331 label: "X",
332 source_range: [48; 48),
333 delete: [48; 48),
334 insert: "X",
335 kind: Enum,
336 },
337]"###
338 );
339 }
340
341 #[test]
313 fn completes_module_items() { 342 fn completes_module_items() {
314 assert_debug_snapshot!( 343 assert_debug_snapshot!(
315 do_reference_completion( 344 do_reference_completion(
diff --git a/crates/ra_ide_api/src/completion/presentation.rs b/crates/ra_ide_api/src/completion/presentation.rs
index 48028a2f9..eb480a775 100644
--- a/crates/ra_ide_api/src/completion/presentation.rs
+++ b/crates/ra_ide_api/src/completion/presentation.rs
@@ -72,7 +72,7 @@ impl Completions {
72 } 72 }
73 ScopeDef::GenericParam(..) => (CompletionItemKind::TypeParam, None), 73 ScopeDef::GenericParam(..) => (CompletionItemKind::TypeParam, None),
74 ScopeDef::LocalBinding(..) => (CompletionItemKind::Binding, None), 74 ScopeDef::LocalBinding(..) => (CompletionItemKind::Binding, None),
75 ScopeDef::SelfType(..) => ( 75 ScopeDef::AdtSelfType(..) | ScopeDef::ImplSelfType(..) => (
76 CompletionItemKind::TypeParam, // (does this need its own kind?) 76 CompletionItemKind::TypeParam, // (does this need its own kind?)
77 None, 77 None,
78 ), 78 ),