From 816971ebc9207c5fb5779d448613dd171c27f398 Mon Sep 17 00:00:00 2001 From: Ville Penttinen Date: Thu, 21 Feb 2019 12:04:14 +0200 Subject: Implement basic support for Associated Methods and Constants This is done in `infer_path_expr`. When `Resolver::resolve_path` returns `PartiallyResolved`, we use the returned `Resolution` together with the given `segment_index` to check if we can find something matching the segment at segment_index in the impls for that particular type. --- crates/ra_hir/src/nameres.rs | 78 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 62 insertions(+), 16 deletions(-) (limited to 'crates/ra_hir/src/nameres.rs') diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs index bd920bfea..b78a178c1 100644 --- a/crates/ra_hir/src/nameres.rs +++ b/crates/ra_hir/src/nameres.rs @@ -119,6 +119,10 @@ impl PerNs { self.types.is_some() && self.values.is_some() } + pub fn is_values(&self) -> bool { + self.values.is_some() && self.types.is_none() + } + pub fn take(self, namespace: Namespace) -> Option { match namespace { Namespace::Types => self.types, @@ -297,7 +301,14 @@ where ); (res, if res.is_none() { ReachedFixedPoint::No } else { ReachedFixedPoint::Yes }) } else { - self.result.resolve_path_fp(self.db, ResolveMode::Import, original_module, &import.path) + let res = self.result.resolve_path_fp( + self.db, + ResolveMode::Import, + original_module, + &import.path, + ); + + (res.module, res.reached_fixedpoint) }; if reached_fixedpoint != ReachedFixedPoint::Yes { @@ -435,6 +446,27 @@ where } } +#[derive(Debug, Clone)] +pub struct ResolvePathResult { + pub(crate) module: PerNs, + pub(crate) segment_index: Option, + reached_fixedpoint: ReachedFixedPoint, +} + +impl ResolvePathResult { + fn empty(reached_fixedpoint: ReachedFixedPoint) -> ResolvePathResult { + ResolvePathResult::with(PerNs::none(), reached_fixedpoint, None) + } + + fn with( + module: PerNs, + reached_fixedpoint: ReachedFixedPoint, + segment_index: Option, + ) -> ResolvePathResult { + ResolvePathResult { module, reached_fixedpoint, segment_index } + } +} + #[derive(Debug, Clone, Copy, PartialEq, Eq)] enum ResolveMode { Import, @@ -468,8 +500,9 @@ impl ItemMap { db: &impl PersistentHirDatabase, original_module: Module, path: &Path, - ) -> PerNs { - self.resolve_path_fp(db, ResolveMode::Other, original_module, path).0 + ) -> (PerNs, Option) { + let res = self.resolve_path_fp(db, ResolveMode::Other, original_module, path); + (res.module, res.segment_index) } fn resolve_in_prelude( @@ -534,7 +567,7 @@ impl ItemMap { mode: ResolveMode, original_module: Module, path: &Path, - ) -> (PerNs, ReachedFixedPoint) { + ) -> ResolvePathResult { let mut segments = path.segments.iter().enumerate(); let mut curr_per_ns: PerNs = match path.kind { PathKind::Crate => PerNs::types(original_module.crate_root(db).into()), @@ -549,7 +582,7 @@ impl ItemMap { { let segment = match segments.next() { Some((_, segment)) => segment, - None => return (PerNs::none(), ReachedFixedPoint::Yes), + None => return ResolvePathResult::empty(ReachedFixedPoint::Yes), }; log::debug!("resolving {:?} in crate root (+ extern prelude)", segment); self.resolve_name_in_crate_root_or_extern_prelude( @@ -561,7 +594,7 @@ impl ItemMap { PathKind::Plain => { let segment = match segments.next() { Some((_, segment)) => segment, - None => return (PerNs::none(), ReachedFixedPoint::Yes), + None => return ResolvePathResult::empty(ReachedFixedPoint::Yes), }; log::debug!("resolving {:?} in module", segment); self.resolve_name_in_module(db, original_module, &segment.name) @@ -571,20 +604,20 @@ impl ItemMap { PerNs::types(p.into()) } else { log::debug!("super path in root module"); - return (PerNs::none(), ReachedFixedPoint::Yes); + return ResolvePathResult::empty(ReachedFixedPoint::Yes); } } PathKind::Abs => { // 2018-style absolute path -- only extern prelude let segment = match segments.next() { Some((_, segment)) => segment, - None => return (PerNs::none(), ReachedFixedPoint::Yes), + None => return ResolvePathResult::empty(ReachedFixedPoint::Yes), }; if let Some(def) = self.extern_prelude.get(&segment.name) { log::debug!("absolute path {:?} resolved to crate {:?}", path, def); PerNs::types(*def) } else { - return (PerNs::none(), ReachedFixedPoint::No); // extern crate declarations can add to the extern prelude + return ResolvePathResult::empty(ReachedFixedPoint::No); // extern crate declarations can add to the extern prelude } } }; @@ -598,7 +631,7 @@ impl ItemMap { // (don't break here because `curr_per_ns` might contain // something in the value namespace, and it would be wrong // to return that) - return (PerNs::none(), ReachedFixedPoint::No); + return ResolvePathResult::empty(ReachedFixedPoint::No); } }; // resolve segment in curr @@ -612,15 +645,15 @@ impl ItemMap { }; log::debug!("resolving {:?} in other crate", path); let item_map = db.item_map(module.krate); - let def = item_map.resolve_path(db, *module, &path); - return (def, ReachedFixedPoint::Yes); + let (def, s) = item_map.resolve_path(db, *module, &path); + return ResolvePathResult::with(def, ReachedFixedPoint::Yes, s); } match self[module.module_id].items.get(&segment.name) { Some(res) if !res.def.is_none() => res.def, _ => { log::debug!("path segment {:?} not found", segment.name); - return (PerNs::none(), ReachedFixedPoint::No); + return ResolvePathResult::empty(ReachedFixedPoint::No); } } } @@ -629,9 +662,22 @@ impl ItemMap { tested_by!(item_map_enum_importing); match e.variant(db, &segment.name) { Some(variant) => PerNs::both(variant.into(), variant.into()), - None => PerNs::none(), + None => { + return ResolvePathResult::with( + PerNs::types((*e).into()), + ReachedFixedPoint::Yes, + Some(i), + ); + } } } + ModuleDef::Struct(s) => { + return ResolvePathResult::with( + PerNs::types((*s).into()), + ReachedFixedPoint::Yes, + Some(i), + ); + } _ => { // could be an inherent method call in UFCS form // (`Struct::method`), or some other kind of associated @@ -641,11 +687,11 @@ impl ItemMap { segment.name, curr, ); - return (PerNs::none(), ReachedFixedPoint::Yes); + return ResolvePathResult::empty(ReachedFixedPoint::Yes); } }; } - (curr_per_ns, ReachedFixedPoint::Yes) + ResolvePathResult::with(curr_per_ns, ReachedFixedPoint::Yes, None) } } -- cgit v1.2.3 From 2e7bc905be156a007a4ee8f1a1bd1d73a1d19ade Mon Sep 17 00:00:00 2001 From: Ville Penttinen Date: Thu, 21 Feb 2019 23:57:07 +0200 Subject: Remove Const inference for now, refactor PathResult --- crates/ra_hir/src/nameres.rs | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) (limited to 'crates/ra_hir/src/nameres.rs') diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs index b78a178c1..b18721104 100644 --- a/crates/ra_hir/src/nameres.rs +++ b/crates/ra_hir/src/nameres.rs @@ -119,10 +119,6 @@ impl PerNs { self.types.is_some() && self.values.is_some() } - pub fn is_values(&self) -> bool { - self.values.is_some() && self.types.is_none() - } - pub fn take(self, namespace: Namespace) -> Option { match namespace { Namespace::Types => self.types, @@ -671,23 +667,20 @@ impl ItemMap { } } } - ModuleDef::Struct(s) => { - return ResolvePathResult::with( - PerNs::types((*s).into()), - ReachedFixedPoint::Yes, - Some(i), - ); - } - _ => { + s => { // could be an inherent method call in UFCS form - // (`Struct::method`), or some other kind of associated - // item... Which we currently don't handle (TODO) + // (`Struct::method`), or some other kind of associated item log::debug!( "path segment {:?} resolved to non-module {:?}, but is not last", segment.name, curr, ); - return ResolvePathResult::empty(ReachedFixedPoint::Yes); + + return ResolvePathResult::with( + PerNs::types((*s).into()), + ReachedFixedPoint::Yes, + Some(i), + ); } }; } -- cgit v1.2.3 From a34eb98a781453a66ce0442e1f7722c0774ae49f Mon Sep 17 00:00:00 2001 From: Ville Penttinen Date: Fri, 22 Feb 2019 00:11:21 +0200 Subject: Make nameres::ResolvePathResult private and refactor --- crates/ra_hir/src/nameres.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'crates/ra_hir/src/nameres.rs') diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs index b18721104..8067b8415 100644 --- a/crates/ra_hir/src/nameres.rs +++ b/crates/ra_hir/src/nameres.rs @@ -304,7 +304,7 @@ where &import.path, ); - (res.module, res.reached_fixedpoint) + (res.resolved_def, res.reached_fixedpoint) }; if reached_fixedpoint != ReachedFixedPoint::Yes { @@ -443,9 +443,9 @@ where } #[derive(Debug, Clone)] -pub struct ResolvePathResult { - pub(crate) module: PerNs, - pub(crate) segment_index: Option, +struct ResolvePathResult { + resolved_def: PerNs, + segment_index: Option, reached_fixedpoint: ReachedFixedPoint, } @@ -455,11 +455,11 @@ impl ResolvePathResult { } fn with( - module: PerNs, + resolved_def: PerNs, reached_fixedpoint: ReachedFixedPoint, segment_index: Option, ) -> ResolvePathResult { - ResolvePathResult { module, reached_fixedpoint, segment_index } + ResolvePathResult { resolved_def, reached_fixedpoint, segment_index } } } @@ -498,7 +498,7 @@ impl ItemMap { path: &Path, ) -> (PerNs, Option) { let res = self.resolve_path_fp(db, ResolveMode::Other, original_module, path); - (res.module, res.segment_index) + (res.resolved_def, res.segment_index) } fn resolve_in_prelude( -- cgit v1.2.3