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, None => None,
} }
} }
pub fn is_transparent(&self) -> bool {
!matches!(self.kind, DefKind::Type(_))
}
} }
mod builder_functions { mod builder_functions {

View File

@ -19,13 +19,17 @@ impl<'p> Path<'p> {
let Self { absolute, parts } = self; let Self { absolute, parts } = self;
Some(Self { absolute, parts: parts.get(1..)? }) 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 { pub fn is_empty(&self) -> bool {
self.parts.is_empty() self.parts.is_empty()
} }
pub fn len(&self) -> usize { pub fn len(&self) -> usize {
self.parts.len() self.parts.len()
} }
pub fn front(&self) -> Option<&PathPart> { pub fn first(&self) -> Option<&PathPart> {
self.parts.first() self.parts.first()
} }
} }

View File

@ -88,18 +88,32 @@ impl<'a> Project<'a> {
return self.get(path.relative(), self.root_of(within)); return self.get(path.relative(), self.root_of(within));
} }
match path.as_ref() { 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)] => { [PathPart::Ident(name)] => {
let (ty, val) = self[within].module.get(*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()?)) Some((ty, val, path.pop_front()?))
} }
[PathPart::Ident(name), ..] => { [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) self.get(path.pop_front()?, ty)
} }
[PathPart::SelfTy, ..] => self.get(path.pop_front()?, self.selfty_of(within)?), [] => Some((Some(within), None, path)),
[PathPart::SelfKw, ..] => self.get(path.pop_front()?, within),
[PathPart::SuperKw, ..] => self.get(path.pop_front()?, self.parent_of(within)?),
} }
} }
@ -108,7 +122,7 @@ impl<'a> Project<'a> {
pub fn get_type<'p>(&self, path: Path<'p>, within: DefID) -> Option<(DefID, Path<'p>)> { pub fn get_type<'p>(&self, path: Path<'p>, within: DefID) -> Option<(DefID, Path<'p>)> {
if path.absolute { if path.absolute {
self.get_type(path.relative(), self.root_of(within)) 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; let module = &self[within].module;
match front { match front {
PathPart::SelfKw => self.get_type(path.pop_front()?, within), 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 /// Inserts the type returned by the provided closure iff the TypeKind doesn't already exist
/// ///
/// Assumes `kind` uniquely identifies the type! /// 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")?; .map_err(|_| "Unresolved type in impl target")?;
prj[id].module.parent = Some(target);
match prj.pool.get_many_mut([id, target]) { match prj.pool.get_many_mut([id, target]) {
// TODO: Better error handling // TODO: Better error handling
Err(_) => Err(concat!( Err(_) => Err(concat!(