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 +++---- crates/ra_hir/src/resolve.rs | 78 ++++++++++++++++------ crates/ra_hir/src/ty.rs | 55 ++++++--------- .../snapshots/tests__infer_associated_const.snap | 14 ++-- 4 files changed, 93 insertions(+), 77 deletions(-) (limited to 'crates/ra_hir') 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), + ); } }; } diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs index 00b55eae9..9f4d4ab42 100644 --- a/crates/ra_hir/src/resolve.rs +++ b/crates/ra_hir/src/resolve.rs @@ -33,27 +33,68 @@ pub(crate) struct ExprScope { } #[derive(Debug, Clone)] -pub enum PathResult { - /// Path was fully resolved - FullyResolved(PerNs), - /// Path was partially resolved, first element contains the resolution - /// second contains the index in the Path.segments which we were unable to resolve - PartiallyResolved(PerNs, usize), +pub struct PathResult { + /// The actual path resolution + resolution: PerNs, + /// The first index in the path that we + /// were unable to resolve. + /// When path is fully resolved, this is 0. + remaining_index: usize, } impl PathResult { - pub fn segment_index(&self) -> Option { - match self { - PathResult::FullyResolved(_) => None, - PathResult::PartiallyResolved(_, ref i) => Some(*i), + /// Returns the remaining index in the result + /// returns None if the path was fully resolved + pub fn remaining_index(&self) -> Option { + if self.remaining_index > 0 { + Some(self.remaining_index) + } else { + None } } /// Consumes `PathResult` and returns the contained `PerNs` + /// if the path was fully resolved, meaning we have no remaining items pub fn into_per_ns(self) -> PerNs { - match self { - PathResult::FullyResolved(def) => def, - PathResult::PartiallyResolved(def, _) => def, + if self.remaining_index().is_none() { + self.resolution + } else { + PerNs::none() + } + } + + /// Consumes `PathResult` and returns the resolution and the + /// remaining_index as a tuple. + pub fn into_inner(self) -> (PerNs, Option) { + let index = self.remaining_index(); + (self.resolution, index) + } + + /// Path is fully resolved when `remaining_index` is none + /// and the resolution contains anything + pub fn is_fully_resolved(&self) -> bool { + !self.resolution.is_none() && self.remaining_index().is_none() + } + + /// Empty path result is where the resolution is `none` + /// and the remaining index is 0 + pub fn is_empty(&self) -> bool { + self.resolution.is_none() && self.remaining_index().is_none() + } + + fn empty() -> PathResult { + PathResult { resolution: PerNs::none(), remaining_index: 0 } + } + + fn from_resolution(res: PerNs) -> PathResult { + PathResult::from_resolution_with_index(res, 0) + } + + fn from_resolution_with_index(res: PerNs, remaining_index: usize) -> PathResult { + if res.is_none() { + PathResult::empty() + } else { + PathResult { resolution: res, remaining_index } } } } @@ -94,24 +135,23 @@ impl Resolver { } pub fn resolve_path(&self, db: &impl HirDatabase, path: &Path) -> PathResult { - use self::PathResult::*; if let Some(name) = path.as_ident() { - FullyResolved(self.resolve_name(db, name)) + PathResult::from_resolution(self.resolve_name(db, name)) } else if path.is_self() { - FullyResolved(self.resolve_name(db, &Name::self_param())) + PathResult::from_resolution(self.resolve_name(db, &Name::self_param())) } else { let (item_map, module) = match self.module() { Some(m) => m, - _ => return FullyResolved(PerNs::none()), + _ => return PathResult::empty(), }; let (module_res, segment_index) = item_map.resolve_path(db, module, path); let def = module_res.map(Resolution::Def); if let Some(index) = segment_index { - PartiallyResolved(def, index) + PathResult::from_resolution_with_index(def, index) } else { - FullyResolved(def) + PathResult::from_resolution(def) } } } diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 2751ab3ab..b1f35ab1f 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs @@ -32,20 +32,17 @@ use rustc_hash::FxHashMap; use test_utils::tested_by; -use ra_syntax::ast::NameOwner; - use crate::{ Function, Struct, StructField, Enum, EnumVariant, Path, Name, - Const, FnSignature, ModuleDef, AdtDef, HirDatabase, type_ref::{TypeRef, Mutability}, - name::{KnownName, AsName}, + name::{KnownName}, expr::{Body, Expr, BindingAnnotation, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, FieldPat, self}, generics::GenericParams, path::GenericArg, adt::VariantDef, - resolve::{Resolver, Resolution, PathResult}, nameres::Namespace + resolve::{Resolver, Resolution}, nameres::Namespace }; /// The ID of a type variable. @@ -681,19 +678,6 @@ fn type_for_fn(db: &impl HirDatabase, def: Function) -> Ty { Ty::FnDef { def: def.into(), sig, name, substs } } -fn type_for_const(db: &impl HirDatabase, resolver: &Resolver, def: Const) -> Ty { - let node = def.source(db).1; - - let tr = node - .type_ref() - .map(TypeRef::from_ast) - .as_ref() - .map(|tr| Ty::from_hir(db, resolver, tr)) - .unwrap_or_else(|| Ty::Unknown); - - tr -} - /// Compute the type of a tuple struct constructor. fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty { let var_data = def.variant_data(db); @@ -1190,21 +1174,28 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { fn infer_path_expr(&mut self, resolver: &Resolver, path: &Path) -> Option { let resolved = resolver.resolve_path(self.db, &path); - let (resolved, segment_index) = match resolved { - PathResult::FullyResolved(def) => (def.take_values()?, None), - PathResult::PartiallyResolved(def, index) => (def.take_types()?, Some(index)), - }; + let (def, remaining_index) = resolved.into_inner(); + + // if the remaining_index is None, we expect the path + // to be fully resolved, in this case we continue with + // the default by attempting to `take_values´ from the resolution. + // Otherwise the path was partially resolved, which means + // we might have resolved into a type for which + // we may find some associated item starting at the + // path.segment pointed to by `remaining_index´ + let resolved = + if remaining_index.is_none() { def.take_values()? } else { def.take_types()? }; match resolved { Resolution::Def(def) => { let typable: Option = def.into(); let typable = typable?; - if let Some(segment_index) = segment_index { + if let Some(remaining_index) = remaining_index { let ty = self.db.type_for_def(typable, Namespace::Types); - // TODO: What to do if segment_index is not the last segment - // in the path - let segment = &path.segments[segment_index]; + // TODO: Keep resolving the segments + // if we have more segments to process + let segment = &path.segments[remaining_index]; // Attempt to find an impl_item for the type which has a name matching // the current segment @@ -1216,17 +1207,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { } None } - crate::ImplItem::Const(c) => { - let node = c.source(self.db).1; - - if let Some(name) = node.name().map(|n| n.as_name()) { - if segment.name == name { - return Some(type_for_const(self.db, resolver, c)); - } - } - None - } + // TODO: Resolve associated const + crate::ImplItem::Const(_) => None, // TODO: Resolve associated types crate::ImplItem::Type(_) => None, diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_associated_const.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_associated_const.snap index 14ab8ba96..131d1fa16 100644 --- a/crates/ra_hir/src/ty/snapshots/tests__infer_associated_const.snap +++ b/crates/ra_hir/src/ty/snapshots/tests__infer_associated_const.snap @@ -1,14 +1,14 @@ --- -created: "2019-02-20T11:04:56.553382800Z" +created: "2019-02-21T21:51:46.497925200Z" creator: insta@0.6.3 source: crates/ra_hir/src/ty/tests.rs expression: "&result" --- [227; 305) '{ ...:ID; }': () -[237; 238) 'x': u32 -[241; 252) 'Struct::FOO': u32 -[262; 263) 'y': u32 -[266; 275) 'Enum::BAR': u32 -[285; 286) 'z': u32 -[289; 302) 'TraitTest::ID': u32 +[237; 238) 'x': [unknown] +[241; 252) 'Struct::FOO': [unknown] +[262; 263) 'y': [unknown] +[266; 275) 'Enum::BAR': [unknown] +[285; 286) 'z': [unknown] +[289; 302) 'TraitTest::ID': [unknown] -- cgit v1.2.3