Implement Linearization for dependency resolution#279
Conversation
e4183d9 to
a807f7f
Compare
|
Is this up to date: #238? |
Yes, but it is much more optimized and has been refactored extensively |
src/driver/c3_linearization.rs
Outdated
| let mut seqs: Vec<Vec<usize>> = Vec::with_capacity(parents.len() + 1); | ||
|
|
||
| for &parent in parents { | ||
| seqs.push(self.linearize_rec(parent, memo, visiting)?); | ||
| } | ||
|
|
||
| let mut result = vec![module]; | ||
| let merged = c3_merge(seqs).map_err(|conflicts| C3Error::InconsistentLinearization { | ||
| module: self.modules[module].source.str_name(), | ||
| conflicts: self.format_conflict_names(conflicts), | ||
| })?; |
There was a problem hiding this comment.
From what I understand the C3 should merge each parent linearization plus the raw parents list, otherwise the direct parent order is never part of the constraints. With the current code, parents [A, B] and linearizations [A] / [B, A] produce [B, A], even though that order contradicts the explicit parent list.
There was a problem hiding this comment.
#[test]
fn test_c3_rejects_conflicting_direct_parent_order() {
// main declares parents in the order [A, B].
// But B itself depends on A, so B's linearization is [B, A].
//
// True C3 must merge:
// [A]
// [B, A]
// [A, B] <- the raw parent list
//
// That merge has no valid head, so this must be rejected as inconsistent.
let (graph, _, _dir) = setup_graph(vec![
("main.simf", "use lib::A::foo; use lib::B::bar;"),
("libs/lib/A.simf", ""),
("libs/lib/B.simf", "use lib::A::foo;"),
]);
let order = graph.c3_linearize();
assert!(
matches!(order, Err(C3Error::InconsistentLinearization { .. })),
"expected inconsistent linearization, got {order:?}"
);
}
There was a problem hiding this comment.
Fixed and added a new test. I accidentally missed adding the parents' order to the sequences when I refactored the code
There was a problem hiding this comment.
Update: I was mistaken in my previous comment. The test_c3_allows_valid_parent_chain() proves that we cannot enforce strict C3 parent order without breaking valid module imports. I have retained the 'Dependency-Driven' C3 approach and added a top-level docstring to formally document this architectural decision
There was a problem hiding this comment.
Update 2: Taking this logic a step further—since we explicitly do not want to enforce strict local precedence for module imports, carrying the C3 is actually unnecessary. A standard post-order DFS provides this as well, but without overhead
src/driver/c3_linearization.rs
Outdated
| ]); | ||
|
|
||
| let order = graph.c3_linearize(); | ||
| matches!(order, Err(C3Error::CycleDetected(_))); |
There was a problem hiding this comment.
matches! just returns a boolean... the result is discarded here
a807f7f to
51b9ceb
Compare
Now the valid import sequence is rejected |
|
Also, is it expected that the order is top-down? |
src/driver/c3_linearization.rs
Outdated
|
|
||
| use crate::driver::DependencyGraph; | ||
|
|
||
| impl DependencyGraph { |
There was a problem hiding this comment.
Give a link in the rust doc to the parent structure pls
927cfb4 to
a49865f
Compare
I have decided to move |
a49865f to
105ea6f
Compare
105ea6f to
9ca524c
Compare
This PR introduces the Linearization algorithm to manage module dependencies. It handles complex dependency topologies, detects cycles, and ensures strict, deterministic load ordering.