为何Rust中Arc<dyn Any + Sync + Send>在两种场景下表现不同?
为什么Rust中两种Option<Arc>传参方式一个可行一个报错?
代码示例
use std::sync::Arc; use std::any::Any; fn main() { // 此调用可行 let this_is_arc_string = Arc::new("this is &str".to_string()); foo(&Some(this_is_arc_string.clone())); // 先将值包装进Option let this_is_arc_string_wrapped_by_option = Some(this_is_arc_string.clone()); // 此判断会返回true println!("is same : {}",&Some(this_is_arc_string.clone()).eq(&this_is_arc_string_wrapped_by_option)); // 编译器报错:"mismatched types[E0308]" foo(&this_is_arc_string_wrapped_by_option); } fn foo(args: &Option<Arc<dyn Any + Sync + Send>>) {}
报错信息
mismatched types [E0308]
expected&Option<Arc<dyn Any + Send + Sync>>, found&Option<Arc<String>>
Note: expected reference&std::option::Option<Arc<(dyn Any + Send + Sync + 'static)>>found reference&std::option::Option<Arc<std::string::String>>
Help:std::string::StringimplementsAnyso you could box the found value and coerce it to the trait objectBox<dyn Any>, you will have to change the expected type as well
Note: function defined here
原因解析
这本质是Rust的trait对象隐式强制转换的时机限制导致的差异:
- 第一次调用时,
Some(this_is_arc_string.clone())是临时值,编译器在推导函数参数类型时,会直接把内部的Arc<String>转换为Arc<dyn Any + Sync + Send>trait对象,同时将整个Option的类型推导为Option<Arc<dyn Any + Sync + Send>>,最终生成的引用&Option<...>完全匹配foo的参数类型。 - 第二次调用时,
this_is_arc_string_wrapped_by_option被提前绑定为Option<Arc<String>>的具体类型。Rust不允许对已确定类型的容器进行隐式的整体转换——Option<Arc<String>>和Option<Arc<dyn Any + ...>>是完全独立的类型,trait对象的转换只能作用于单个值(比如Arc<String>转Arc<dyn Any>),无法直接穿透到外层的Option容器上。
另外需要注意:eq方法返回true只是因为Option的相等判断支持内部值可比较的不同Option类型,并不代表两者的类型相同。
内容的提问来源于stack exchange,提问作者Richard Jiang
相关产品推荐
相关产品推荐

