Rust trait默认实现方法中self类型不符合预期问题排查
Rust trait默认方法中Arc包裹引用引发的编译错误
问题描述
定义了如下FileSystem trait:
use std::fmt::Debug; use std::sync::Arc; pub trait FileSystem: Debug + Send + Sync {} #[derive(Debug)] pub struct FileSystemLocation { file_system: Arc<dyn FileSystem>, sub_path: Vec<String>, } impl FileSystemLocation { pub fn new(file_system: Arc<dyn FileSystem>, sub_path: Vec<String>) -> Self { Self { file_system, sub_path, } } }
并在该trait中添加了带默认逻辑的方法:
pub trait FileSystem: Debug + Send + Sync { fn location_with_sub_path(&self, sub_path: &[&str]) -> FileSystemLocation { FileSystemLocation::new( Arc::new(self), sub_path .into_iter() .map(|s| s.to_string()) .collect() ) } }
编译时出现错误:
error[E0277]: the trait bound `&Self: FileSystem` is not satisfied --> src\file_system_location\file_system\mod.rs:52:13 | 52 | Arc::new(self), | ^^^^^^^^^^^^^^ the trait `FileSystem` is not implemented for `&Self` | = help: the following other types implement trait `FileSystem`: LocalFileSystem VirtualFileSystem = note: required for the cast from `Arc<&Self>` to `Arc<(dyn FileSystem + 'static)>`
问题原因
Rust中,当某个类型T实现了自定义trait时,并不会自动为其引用类型&T也实现该trait。虽然Self(实现FileSystem的具体类型)满足trait约束,但&Self(该类型的引用)并没有实现FileSystem,因此Arc<&Self>无法被转换为Arc<dyn FileSystem>。
解决方案
方案1:为所有FileSystem类型的引用实现trait
通过通用实现,让任何实现了FileSystem的类型的引用也自动实现该trait:
impl<T: FileSystem + ?Sized> FileSystem for &T {}
这样&Self就满足了FileSystem约束,Arc<&Self>可以被转换为Arc<dyn FileSystem>,编译即可通过。如果trait中有其他需要实现的方法,需要在这个通用实现中转发调用,例如:
impl<T: FileSystem + ?Sized> FileSystem for &T { // 假设有read_file方法,转发到内部引用的实现 fn read_file(&self, path: &str) -> Result<String, std::io::Error> { (**self).read_file(path) } }
方案2:调整默认方法,获取Arc<Self>而非Arc<&Self>
如果trait实现者通常被Arc持有,可以修改默认方法,要求Self实现Clone,通过克隆自身来创建Arc:
pub trait FileSystem: Debug + Send + Sync + Clone + Sized { fn location_with_sub_path(&self, sub_path: &[&str]) -> FileSystemLocation { FileSystemLocation::new( Arc::new(self.clone()), sub_path.into_iter().map(|s| s.to_string()).collect() ) } }
这种方式会给trait添加额外约束(Clone + Sized),需根据实际场景选择。
内容的提问来源于stack exchange,提问作者Jamzy01
相关产品推荐
相关产品推荐

