我有这个简化的 Rust 代码:
use std::io::Result;
pub trait PacketBuffer {}
pub trait DnsRecordData {
fn write<T: PacketBuffer>(&self, buffer: &mut T) -> Result<usize>;
}
pub struct DnsRecord<R: DnsRecordData + ?Sized> {
pub data: Box<R>,
}
pub struct DnsPacket {
pub answers: Vec<DnsRecord<dyn DnsRecordData>>,
}
目的是 DnsRecord
应该能够保存任何实现 DnsRecordData
特性的结构,不同的结构代表 A、AAAA、CNAME 等。
失败并出现错误:
error[E0038]: the trait `DnsRecordData` cannot be made into an object
--> src/lib.rs:14:5
|
14 | pub answers: Vec<DnsRecord<dyn DnsRecordData>>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `DnsRecordData` cannot be made into an object
|
= note: method `write` has generic type parameters
最让我困惑的是,通过从 DnsRecordData::write()
中删除泛型,它编译得很好:
use std::io::Result;
pub trait PacketBuffer {}
pub trait DnsRecordData {
fn write(&self, buffer: &mut dyn PacketBuffer) -> Result<usize>;
}
pub struct DnsRecord<R: DnsRecordData + ?Sized> {
pub data: Box<R>,
}
pub struct DnsPacket {
pub answers: Vec<DnsRecord<dyn DnsRecordData>>,
}
如果有人能解释我遗漏了什么,我将不胜感激。
最佳答案
该错误是由于您无法为 DnsRecordData
创建特征对象,因为该特征不是“对象安全的”。 trait objects section of The Rust Programming Language 中解释了这个概念。 .
在您的特定情况下,特征包含一个通用方法。要创建特征对象,编译器必须为特征合成一个 vtable,其中包含特征具有的每个方法的函数指针。但是因为 trait 有一个泛型方法,它实际上有尽可能多的方法可以被实例化,这可能是无限的。因此,您不能为 DnsRecordData
创建特征对象。
关于generics - 无法创建多态类型,因为无法将特征制成对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39412626/