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:
John 2024-07-21 06:01:54 -05:00
parent 6bf34fdff6
commit 70872d86f9
4 changed files with 29 additions and 18 deletions

View File

@ -28,6 +28,10 @@ impl Def<'_> {
None => None,
}
}
pub fn is_transparent(&self) -> bool {
!matches!(self.kind, DefKind::Type(_))
}
}
mod builder_functions {

View File

@ -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()
}
}

View File

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

View File

@ -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!(