cl-typeck: Improve path resolution semantics, and DON'T REPARENT IMPLs
- Perform heirarchical resolution through "transparent" nodes - Reparenting impls broke relative path traversal entirely. To impl something, it must already be in scope anyway. - TODO: well-formedness checks?
This commit is contained in:
parent
6bf34fdff6
commit
70872d86f9
@ -28,6 +28,10 @@ impl Def<'_> {
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_transparent(&self) -> bool {
|
||||
!matches!(self.kind, DefKind::Type(_))
|
||||
}
|
||||
}
|
||||
|
||||
mod builder_functions {
|
||||
|
@ -19,13 +19,17 @@ impl<'p> Path<'p> {
|
||||
let Self { absolute, parts } = self;
|
||||
Some(Self { absolute, parts: parts.get(1..)? })
|
||||
}
|
||||
pub fn front(self) -> Option<Self> {
|
||||
let Self { absolute, parts } = self;
|
||||
Some(Self { absolute, parts: parts.get(..1)? })
|
||||
}
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.parts.is_empty()
|
||||
}
|
||||
pub fn len(&self) -> usize {
|
||||
self.parts.len()
|
||||
}
|
||||
pub fn front(&self) -> Option<&PathPart> {
|
||||
pub fn first(&self) -> Option<&PathPart> {
|
||||
self.parts.first()
|
||||
}
|
||||
}
|
||||
|
@ -88,18 +88,32 @@ impl<'a> Project<'a> {
|
||||
return self.get(path.relative(), self.root_of(within));
|
||||
}
|
||||
match path.as_ref() {
|
||||
[] => Some((Some(within), None, path)),
|
||||
[PathPart::SuperKw, ..] => self.get(path.pop_front()?, self.parent_of(within)?),
|
||||
[PathPart::SelfTy, ..] => self.get(path.pop_front()?, self.selfty_of(within)?),
|
||||
[PathPart::SelfKw, ..] => self.get(path.pop_front()?, within),
|
||||
[PathPart::Ident(name)] => {
|
||||
let (ty, val) = self[within].module.get(*name);
|
||||
|
||||
// Transparent nodes can be looked through in reverse
|
||||
if self[within].is_transparent() {
|
||||
let lookback = self.parent_of(within).and_then(|p| self.get(path, p));
|
||||
if let Some((subty, subval, path)) = lookback {
|
||||
return Some((ty.or(subty), val.or(subval), path));
|
||||
}
|
||||
}
|
||||
Some((ty, val, path.pop_front()?))
|
||||
}
|
||||
[PathPart::Ident(name), ..] => {
|
||||
let ty = self[within].module.get_type(*name)?;
|
||||
// TODO: This is currently too permissive, and treats undecided nodes as if they're
|
||||
// always transparent, among other issues.
|
||||
let (tysub, _, _) = match self[within].is_transparent() {
|
||||
true => self.get(path.front()?, within)?,
|
||||
false => (None, None, path),
|
||||
};
|
||||
let ty = self[within].module.get_type(*name).or(tysub)?;
|
||||
self.get(path.pop_front()?, ty)
|
||||
}
|
||||
[PathPart::SelfTy, ..] => self.get(path.pop_front()?, self.selfty_of(within)?),
|
||||
[PathPart::SelfKw, ..] => self.get(path.pop_front()?, within),
|
||||
[PathPart::SuperKw, ..] => self.get(path.pop_front()?, self.parent_of(within)?),
|
||||
[] => Some((Some(within), None, path)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -108,7 +122,7 @@ impl<'a> Project<'a> {
|
||||
pub fn get_type<'p>(&self, path: Path<'p>, within: DefID) -> Option<(DefID, Path<'p>)> {
|
||||
if path.absolute {
|
||||
self.get_type(path.relative(), self.root_of(within))
|
||||
} else if let Some(front) = path.front() {
|
||||
} else if let Some(front) = path.first() {
|
||||
let module = &self[within].module;
|
||||
match front {
|
||||
PathPart::SelfKw => self.get_type(path.pop_front()?, within),
|
||||
@ -124,16 +138,6 @@ impl<'a> Project<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_value<'p>(&self, path: Path<'p>, within: DefID) -> Option<(DefID, Path<'p>)> {
|
||||
match path.front()? {
|
||||
PathPart::Ident(name) => Some((
|
||||
self[within].module.values.get(name).copied()?,
|
||||
path.pop_front()?,
|
||||
)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Inserts the type returned by the provided closure iff the TypeKind doesn't already exist
|
||||
///
|
||||
/// Assumes `kind` uniquely identifies the type!
|
||||
|
@ -271,7 +271,6 @@ impl<'a> TypeResolvable<'a> for &'a Impl {
|
||||
}
|
||||
.map_err(|_| "Unresolved type in impl target")?;
|
||||
|
||||
prj[id].module.parent = Some(target);
|
||||
match prj.pool.get_many_mut([id, target]) {
|
||||
// TODO: Better error handling
|
||||
Err(_) => Err(concat!(
|
||||
|
Loading…
Reference in New Issue
Block a user