Rust 编译器不允许Self
在特征方法的返回类型中指定新类型参数。也就是说,特征方法可以返回Self
,但不能Self<T>
。我感兴趣的是完成以下任务的正确方法是什么;或者如果这根本不可能,那么为什么会这样。
假设我们有两个结构体,如下所示:
pub struct SomeStruct<T> {
id: usize,
description: String,
extra_data: T,
}
pub struct OtherStruct<T> {
permit_needed: bool,
registration_number: usize,
extra_data: T,
}
Run Code Online (Sandbox Code Playgroud)
这两个结构体都有一个extra_data
类型为 的字段T
,其中T
是泛型类型参数。我们可以在这两个结构上实现诸如get_extra_data()
,更有趣的是 ,之类的方法:transform()
impl<T> SomeStruct<T> {
pub fn get_extra_data(&self) -> &T {
&self.extra_data
}
pub fn transform<S>(&self, data: S) -> SomeStruct<S> {
SomeStruct {
id: self.id,
description: self.description.clone(),
extra_data: data,
}
}
}
impl<T> OtherStruct<T> {
pub fn get_extra_data(&self) -> &T {
&self.extra_data
}
pub fn transform<S>(&self, data: S) -> OtherStruct<S> {
OtherStruct {
permit_needed: self.permit_needed,
registration_number: self.registration_number,
extra_data: data,
}
}
}
Run Code Online (Sandbox Code Playgroud)
Transformable
但我在创建一个将这两种类型的操作统一起来的特征时遇到了困难:
trait Transformable<T> {
fn get_extra_data(&self) -> &T;
fn transform<S>(&self, data: S) -> Self<S>;
}
Run Code Online (Sandbox Code Playgroud)
该transform()
函数需要返回与 相同类型的内容Self
,只是具有不同的类型参数。不幸的是,Rust 编译器拒绝了这一点并显示错误消息E0109: type arguments are not allowed for this type
。
即使较弱的签名fn transform<S>(&self, data: S) -> impl Transformable<S>
也会被拒绝,并出现错误E0562: impl Trait not allowed outside of function and inherent method return types
。据我所知,这里的传统解决方案是返回关联类型而不是impl
,但在这种情况下需要泛型关联类型。无论如何,这看起来比更强的要迂回得多Self<S>
我们真正想要的更强的签名要迂回得多。
对于生命周期参数,类似的问题也会以完全相同的方式发生。实际上,我对生命周期参数的情况更感兴趣,但我认为类型参数的情况可能更容易理解和讨论,并且还清楚地表明该问题不是特定于生命周期的。