I am trying to downcast from a 'dyn ValueTrait' into the Function struct, which implements the ValueTrait. When I do it with variables, it seems to work. But when I do it with the interior mutability pattern, it does not. My code looks as follows, and it always results in panic.
// function is a Rc<RefCell<dyn ValueTait>>
let f = match function.as_any().downcast_ref::<Rc<RefCell<Function>>>() {
Some(func) => {
func
},
None => {
panic!("Could not downcast Value to Function")
}
};
Downcasting isn't transitive, so when you call as_any, you can only downcast back to Rc<RefCell<dyn ValueTrait>>. You'll have to get at the dyn ValueTrait inside the RefCell directly to downcat it separately. Something like:
Thanks! it is working now... updated in the same link.
I fought this thing for a couple of days and, now that I manage to get it to work, I notice it reduced significantly reduced the performance of my code .... But, I learned. I will see what happened later.
Thanks a lot!
use std::any::Any;
use std::cell::RefCell;
use std::rc::Rc;
// These two are just placeholders
struct ScriptFn (f64);
struct RustFn (f64);
trait ValueTrait {
fn to_string(&self)->String;
fn type_name(&self)->String;
fn as_any(&self)->&dyn Any;
}
#[allow(dead_code)]
enum Function {
Script(ScriptFn),
Native(RustFn)
}
// Trait for Function
impl ValueTrait for Function {
fn to_string(&self)->String {
"fn Func()".to_string()
}
fn type_name(&self)->String {
"Function".to_string()
}
fn as_any(&self) -> &dyn Any {
self
}
}
// Trait for Values contained in this pattern
impl ValueTrait for Rc<RefCell<dyn ValueTrait>> {
fn to_string(&self)->String {
format!("fn {}()",self.borrow().to_string())
}
fn type_name(&self)->String {
self.borrow().type_name()
}
fn as_any(&self) -> &dyn Any{
self
}
}
fn print_type_of<T>(_: &T) {
println!("{}", std::any::type_name::<T>())
}
fn main() {
// Example with 'raw' variables
let mut values : Vec<&dyn ValueTrait> = Vec::new();
let v = Function::Script(ScriptFn(2.0));
values.push(&v);
let function = values.pop().unwrap();
match function.as_any().downcast_ref::<Function>() {
Some(_) => {
println!("Downcasting Value to Function worked!")
},
None => {
panic!("Could not downcast Value to Function")
}
};
// Example with Mutability Pattern
let mut values : Vec<Rc<RefCell<dyn ValueTrait>>> = Vec::new();
let v = Rc::new(RefCell::new(Function::Script(ScriptFn(2.0))));
values.push(v);
let function = values.pop().unwrap();
let tmp = function.borrow();
let f = match tmp.as_any().downcast_ref::<Function>() {
Some(f) => {
println!("Downcasting Rc<RefCell<Value>> to Function worked!");
f
},
None => {
panic!("Could not downcast Rc<RefCell<Value>> to Function");
}
};
print_type_of(f);
}