Remove Const inference for now, refactor PathResult

This commit is contained in:
Ville Penttinen 2019-02-21 23:57:07 +02:00
parent 816971ebc9
commit 2e7bc905be
4 changed files with 93 additions and 77 deletions

View File

@ -119,10 +119,6 @@ impl<T> PerNs<T> {
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<T> {
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),
);
}
};
}

View File

@ -33,27 +33,68 @@ pub(crate) struct ExprScope {
}
#[derive(Debug, Clone)]
pub enum PathResult {
/// Path was fully resolved
FullyResolved(PerNs<Resolution>),
/// 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<Resolution>, usize),
pub struct PathResult {
/// The actual path resolution
resolution: PerNs<Resolution>,
/// 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<usize> {
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<usize> {
if self.remaining_index > 0 {
Some(self.remaining_index)
} else {
None
}
}
/// Consumes `PathResult` and returns the contained `PerNs<Resolution>`
/// if the path was fully resolved, meaning we have no remaining items
pub fn into_per_ns(self) -> PerNs<Resolution> {
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<Resolution>, Option<usize>) {
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<Resolution>) -> PathResult {
PathResult::from_resolution_with_index(res, 0)
}
fn from_resolution_with_index(res: PerNs<Resolution>, 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)
}
}
}

View File

@ -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<Ty> {
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<TypableDef> = 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,

View File

@ -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]