diff options
author | ice1000 <[email protected]> | 2019-09-27 05:19:52 +0100 |
---|---|---|
committer | ice1000 <[email protected]> | 2019-10-08 00:40:14 +0100 |
commit | 6bad638928ab880bfbad868f07f0690ace2f2c30 (patch) | |
tree | 0c38bc47eda0769ef27c65a5d2bb05e8d4acfd9e /crates | |
parent | c73193efe29ff4072fd19471fb22cdd2ee05556c (diff) |
Support inferring `Self` type in enum definitions
Signed-off-by: ice1000 <[email protected]>
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_hir/src/code_model.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir/src/resolve.rs | 32 | ||||
-rw-r--r-- | crates/ra_hir/src/source_binder.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 3 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/lower.rs | 1 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 19 | ||||
-rw-r--r-- | crates/ra_ide_api/src/completion/presentation.rs | 2 |
7 files changed, 54 insertions, 9 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index e3a7e8e3c..cd501d1f6 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(From::from(self))) |
469 | } | 469 | } |
470 | } | 470 | } |
471 | 471 | ||
diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs index 39f8e1d8a..c46f7e157 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 definition 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..9e5d42509 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs | |||
@@ -559,6 +559,9 @@ 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::Struct(it))) => it.into(), | ||
563 | Some(TypeNs::AdtSelfType(Adt::Union(it))) => it.into(), | ||
564 | Some(TypeNs::AdtSelfType(Adt::Enum(it))) => it.into(), | ||
562 | Some(TypeNs::EnumVariant(it)) => it.into(), | 565 | Some(TypeNs::EnumVariant(it)) => it.into(), |
563 | Some(TypeNs::TypeAlias(it)) => it.into(), | 566 | Some(TypeNs::TypeAlias(it)) => it.into(), |
564 | 567 | ||
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] |
138 | fn infer_adt_self() { | ||
139 | let (db, pos) = MockDatabase::with_position( | ||
140 | r#" | ||
141 | //- /main.rs | ||
142 | enum Nat { Succ(Self), Demo(Nat), Zero } | ||
143 | |||
144 | fn 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] | ||
138 | fn infer_try() { | 157 | fn 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/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 | ), |