Generics 无法创建多态类型,因为无法将特征生成对象

Generics 无法创建多态类型,因为无法将特征生成对象,generics,rust,Generics,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 d

我有一个简化的防锈代码:

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>>,
}
让我最困惑的是,通过从
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>>,
}
使用std::io::Result;
发布特性包缓冲区{}
发布特征DnsRecordData{
fn write(&self,buffer:&mut dyn PacketBuffer)->结果;
}
发布结构DnsRecord{
发布数据:框,
}
发布结构DnsPacket{
酒吧回答:Vec,
}

如果有人能解释我遗漏了什么,我将不胜感激。

错误源于这样一个事实,即您无法为
DnsRecordData
创建trait对象,因为trait不是“对象安全的”。这一概念在本手册中有解释

在您的特定情况下,trait包含一个通用方法。要创建trait对象,编译器必须为trait合成一个vtable,其中包含trait拥有的每个方法的函数指针。但是由于trait有一个泛型方法,因此它实际上拥有尽可能多的方法,因为该方法可以被实例化,这可能是无限的。因此,不能为
DnsRecordData
创建特征对象

其目的是
DnsRecord
应该能够保存实现
DnsRecordData
特性的任何结构

代码上不是这么说的

Vec<DnsRecord<dyn DnsRecordData>>
特质是可以实现的,但它们也有自己的类型。为了创建这种类型,trait需要是对象安全的-

正如错误消息所述,此trait不能是trait对象,因为该方法上存在泛型类型

第一个错误指出,
DnsRecordData
要求参数化它的任何类型都必须实现
DnsRecordData
。但是,trait对象的类型实际上并没有实现这一点。通常,您会通过引用(
&dyn DnsRecordData
)或框(
box
)使用trait对象,这两者都应该实现trait,以防止出现此错误

pub struct DnsPacket<D>
where
    D: DnsRecordData,
{
    pub answers: Vec<DnsRecord<D>>,
}