I'm trying to create a visitor pattern for traversing an AST, and I have the following repro case which is similar to my actual project.
By searching through, I was able to solve it by using .clone()
in the place where the error happens. I want to expose this traversal as a library and I don't think it's a good API if the users are expected to clone an input parameter if they want to even use it?
I'm not able to understand how to use lifetime parameter here in visit_*
functions - because it always returns ()
and only reads that part of the AST and never returns anything.
struct Assignment {
left: Identifier,
right: Identifier,
}
struct Identifier {
name: String,
alias: Option<String>,
}
#[allow(unused_variables)]
trait Visitor {
fn visit_assignment(&mut self, assignment: &Assignment) -> () {}
fn visit_identifier(&mut self, id: &Identifier) -> () {}
}
struct Traversal {
visitor: Box<Visitor>,
}
impl Traversal {
fn handle_identifier(&mut self, identifier: &Identifier) {
self.visitor.visit_identifier(&identifier);
}
fn handle_assignment(&mut self, assignment: &Assignment) {
self.visitor.visit_assignment(&assignment);
let left = &assignment.left;
let right = &assignment.right;
self.handle_identifier(&left);
self.handle_identifier(&right);
}
}
fn traverse(visitor: Box<Visitor>, root: &Assignment) {
let mut traversal = Traversal { visitor };
traversal.handle_assignment(&root);
}
struct PrintVisitor;
impl Visitor for PrintVisitor {
fn visit_identifier(&mut self, id: &Identifier) {
let alias = &id.alias.unwrap();
println!("{}", alias);
}
}
fn main() {
let name = Identifier {
name: "name".to_string(),
alias: None,
};
let value = Identifier {
name: "value".to_string(),
alias: Some("foo".to_string()),
};
let assignment = Assignment {
left: name,
right: value,
};
let visitor = Box::new(PrintVisitor {});
traverse(visitor, &assignment);
}
Errors:
Compiling playground v0.0.1 (file:///playground)
error[E0507]: cannot move out of borrowed content
--> src/main.rs:42:22
|
42 | let alias = &id.alias.unwrap();
| ^^ cannot move out of borrowed content
error: aborting due to previous error
For more information about this error, try `rustc --explain E0507`.
error: Could not compile `playground`.
To learn more, run the command again with --verbose.