Skip to content

Experience report: Integration with Any #2

@crlf0710

Description

@crlf0710

Code description

By using Any as a supertrait, this feature enables quite nice conversions (upcasts and downcasts) between types in a 2-level depth trait-type taxonomy:

use std::any::Any;

trait Node: Any {}

#[derive(Debug)]
struct Node1 {
    data: i32,
}

impl Node for Node1 {}

#[derive(Debug)]
struct Node2 {
    data: f64,
}

impl Node for Node2 {}

fn visit_all_nodes(nodes: &[Box<dyn Node>]) {
    for node in nodes.iter() {
        let node: &dyn Node = &**node;
        if let Some(node1 @ Node1 { .. }) = (node as &dyn Any).downcast_ref::<Node1>() {
            println!("{:?}", node1);
        } else if let Some(node2 @ Node2 { .. }) = (node as &dyn Any).downcast_ref::<Node2>() {
            println!("{:?}", node2);
        } else {
            println!("unknown node");
        }
    }
}

fn main() {
    let nodes: Vec<Box<dyn Node>> =
        vec![Box::new(Node1 { data: 42 }), Box::new(Node2 { data: 99.0 })];
    visit_all_nodes(&nodes[..]);
}

outputs:

Node1 { data: 42 }
Node2 { data: 99.0 }

What worked well

This is much more ergonomic than asking each node to implement as_any_ref and as_any_mut to enable downcasting.

What worked less well

The (node as &dyn Any).downcast_ref syntax still looks a little cumbersome.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions