If I have a Box<dyn Trait1 + Trait2>
, can I return a &dyn Trait1
?
To give some context, I am trying to implement a (specialised) graph in rust. This SpecialisedGraph
needs some standard graph algorithms, and I would like to implement these using the Graph
trait that could be shared across several graph types but this code is not compiling:
trait Node {
//...
}
trait Graph {
fn get_node(&self, key: &str) -> Option<&dyn Node>;
}
trait SpecialisedNode {
//...
}
trait SpecialisedGraphNode: SpecialisedNode + Node {}
struct SpecialisedGraph {
nodes: HashMap<String, Box<dyn SpecialisedGraphNode>>
}
impl Graph for SpecialisedGraph {
fn get_node(&self, key: &str) -> Option<&dyn Node> {
match self.nodes.get(key) {
Some(node) => Some(&(**node)),
None => None
}
}
}
With error:
error[E0308]: mismatched types
--> src\main.rs:25:32
|
25 | Some(node) => Some(&(**node)),
| ^^^^^^^^^ expected trait `Node`, found trait `SpecialisedGraphNode`
|
= note: expected reference `&dyn Node`
found reference `&dyn SpecialisedGraphNode`
EDIT: I have edited the question to reflect the comments
EDIT2: Found the answer to my question using the link Why doesn't Rust support trait object upcasting? provided by Shepmaster.
The updated code below now works, thanks all.
trait AsNode {
fn as_node(&self) -> &dyn Node;
}
trait Node : AsNode {
//...
}
impl<T: Node> AsNode for T {
fn as_node(&self) -> &dyn Node {
self
}
}
trait Graph {
fn get_node(&self, key: &str) -> Option<&dyn Node>;
}
trait SpecialisedNode : Node {
//...
}
struct SpecialisedGraph {
nodes: HashMap<String, Box<dyn SpecialisedNode>>
}
impl Graph for SpecialisedGraph {
fn get_node(&self, key: &str) -> Option<&dyn Node> {
match self.nodes.get(key) {
Some(node) => Some(node.as_node()),
None => None
}
}
}