Trait 方法返回具有不同类型和/或生命周期参数的“Self”类型

Cra*_* D. 5 rust

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>我们真正想要的更强的签名要迂回得多。

带有上述代码的 Playground 链接

对于生命周期参数,类似的问题也会以完全相同的方式发生。实际上,我对生命周期参数的情况更感兴趣,但我认为类型参数的情况可能更容易理解和讨论,并且还清楚地表明该问题不是特定于生命周期的。