Remove Const inference for now, refactor PathResult
This commit is contained in:
parent
816971ebc9
commit
2e7bc905be
@ -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),
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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]
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user