I am very new to the Rust language so please bear with me.
I am implementing a graph data structure in Rust. For each node (and also edges – omitted from this snippet) in the graph I have a struct “Algorithm” (perhaps poorly named) that performs some node and edge based logic. Algorithms require knowledge of the graph connectivity and so cannot belong to a node or edge themselves. They are based on trait polymorphism, although I plan to refactor this to enum polymorphism later. Lastly, I have a solver that works by iterating the nodes of the graph and creating an algorithm for it. Please note, the example is heavily distilled down.
However, I am having two problems. The first is due to the lifetime of the Boxed struct within the “algorithms” vector.
error: lifetime may not live long enough
--> main.rs:67:29
|
51 | impl<'a> Solver<'a> {
| -- lifetime `'a` defined here
...
63 | pub fn solve(&mut self) {
| - let's call the lifetime of this reference `'1`
...
67 | let algorithm = Box::new(MyAlgorithm {
| _____________________________^
68 | | graph: &mut self.graph,
69 | | });
| |______________^ assignment requires that `'1` must outlive `'a`
I have tried my best to indicate to the compiler that the lifetime of the Algorithm struct should be kept within the lifetime of the Solver struct, but this hasn’t worked.
Upon completion of its job, an Algorithm will need to update the nodes and edges of the graph, and so it requires a mutable reference to the graph object. However, this of course is incorrect due to the second mutable borrow.
cannot borrow `self.graph` as mutable more than once at a time
second mutable borrow occurs here
Below is the code.
struct Node {
// Define the Node struct...
}
impl Node {
// Implement methods for Node...
}
struct Graph {
nodes: Vec<Node>,
}
impl Graph {
fn new() -> Self {
Graph {
nodes: Vec::new(),
// Initialize other fields...
}
}
}
trait BaseAlgorithm<'a> {
// Define the trait methods...
}
// Create a MyAlgorithm struct that takes a mutable reference to the graph
struct MyAlgorithm<'a> {
graph: &'a mut Graph,
}
impl<'a> BaseAlgorithm<'a> for MyAlgorithm<'a> {
// Implement the trait methods for MyAlgorithm...
}
struct Solver<'a> {
algorithms: Vec<Box<dyn BaseAlgorithm<'a> + 'a>>,
graph: Graph,
}
impl<'a> Solver<'a> {
fn new() -> Self {
Solver {
algorithms: Vec::new(),
graph: Graph::new(),
}
}
fn add_algorithm(&mut self, algorithm: Box<dyn BaseAlgorithm<'a> + 'a>) {
self.algorithms.push(algorithm);
}
pub fn solve(&mut self) {
// Loop over the nodes vector within Graph
for node in &mut self.graph.nodes {
// add an algorithm with a mutable reference to Graph
let algorithm = Box::new(MyAlgorithm {
graph: &mut self.graph,
});
self.add_algorithm(algorithm);
}
}
}
fn main() {
let mut solver = Solver::new();
solver.solve();
}
If the design can be fixed, then I would greatly appreciate any help achieving that. However, if the design cannot be fixed, is there an idiomatic Rust pattern for achieving the requirements of this logic?