Box<dyn T>何时可强制转换为&dyn T?及as_any模式异常排查
关于Rust中Box调用as_any模式的类型判断问题
背景
我出于兴趣跟随教程编写一个简单解释器,需要判断Box<dyn Expr>中的实例是否为实现了Expr trait的Variable类型,采用了as_any模式。
测试代码与异常现象
最初的测试代码如下:
let e: Box<dyn Expr> = Box::new(Variable{ name: Token{ token_type: TokenType::Number, lexeme: "123".to_string(), literal: Some(LoxValue::Number(123f64)), line: 1 } }); assert!(e.as_any().is::<Variable>()); assert!(e.as_any().downcast_ref::<Variable>().is_some());
这段代码断言成功,且Rust Analyzer提示:
Type Box<dyn Expr, Global> Coerced to: &dyn Expr
但在其他场景中无法复现该行为,必须写(*the_box).as_any().is::<SomeStruct>()才能得到正确结果,否则判断始终返回false。
相关类型定义
pub trait AsAny: Any { fn as_any(&self) -> &dyn Any; } impl<T: Any> AsAny for T { fn as_any(&self) -> &dyn Any { self } } pub trait Expr: AsAny + Debug{ fn evaluate(&self, environment: &mut Environment) -> EvaluateResult; fn boxed(self) -> Box<dyn Expr> where Self: Sized { Box::new(self) } } #[derive(Debug)] pub struct Variable { pub name: Token, } impl Expr for Variable { fn evaluate(&self, environment: &mut Environment) -> super::expr::EvaluateResult { environment.get(self.name.clone()) } }
复现测试
在新创建的包中编写如下代码:
trait AsAny: Any { fn as_any(&self) -> &dyn Any; } impl<T: Any> AsAny for T { fn as_any(&self) -> &dyn Any { self } } struct Foo {} trait TheTrait: AsAny {} impl TheTrait for Foo {} fn main() { let b: Box<dyn TheTrait> = Box::new(Foo{}); println!("{}", b.as_any().is::<Foo>()); println!("{}", (*b).as_any().is::<Foo>()); }
运行后只有第二行println!输出true。
更新说明
(*boxed_thing).as_any().is::<SomeThing>()似乎才是正确写法。可能存在某种bug导致boxed_thing.as_any().is::<Something>()偶然生效,将原代码复制到新位置后断言失败。
内容的提问来源于stack exchange,提问作者Lee
相关产品推荐
相关产品推荐

