From 70872d86f922281ff21a29cca18ca6d339c8e916 Mon Sep 17 00:00:00 2001 From: John Date: Sun, 21 Jul 2024 06:01:54 -0500 Subject: [PATCH] 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? --- compiler/cl-typeck/src/definition.rs | 4 +++ compiler/cl-typeck/src/path.rs | 6 ++++- compiler/cl-typeck/src/project.rs | 36 ++++++++++++++----------- compiler/cl-typeck/src/type_resolver.rs | 1 - 4 files changed, 29 insertions(+), 18 deletions(-) diff --git a/compiler/cl-typeck/src/definition.rs b/compiler/cl-typeck/src/definition.rs index 5e6b172..aba1cf0 100644 --- a/compiler/cl-typeck/src/definition.rs +++ b/compiler/cl-typeck/src/definition.rs @@ -28,6 +28,10 @@ impl Def<'_> { None => None, } } + + pub fn is_transparent(&self) -> bool { + !matches!(self.kind, DefKind::Type(_)) + } } mod builder_functions { diff --git a/compiler/cl-typeck/src/path.rs b/compiler/cl-typeck/src/path.rs index 70be18b..974f87b 100644 --- a/compiler/cl-typeck/src/path.rs +++ b/compiler/cl-typeck/src/path.rs @@ -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 { + 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() } } diff --git a/compiler/cl-typeck/src/project.rs b/compiler/cl-typeck/src/project.rs index 23513f1..1474ad4 100644 --- a/compiler/cl-typeck/src/project.rs +++ b/compiler/cl-typeck/src/project.rs @@ -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! diff --git a/compiler/cl-typeck/src/type_resolver.rs b/compiler/cl-typeck/src/type_resolver.rs index abf261d..e1eef5c 100644 --- a/compiler/cl-typeck/src/type_resolver.rs +++ b/compiler/cl-typeck/src/type_resolver.rs @@ -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!(