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

问题描述

Rust 编译器不允许Self在 trait 方法的返回类型中指定新的类型参数。也就是说,特征方法可以返回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,
}

这两个结构都有一个extra_datatype 字段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,
        }
    }
}

但是我在创建一个Transformable关于这些操作统一这两种类型的特征时遇到了麻烦:


trait Transformable<T> {
    fn get_extra_data(&self) -> &T;
    fn transform<S>(&self, data: S) -> Self<S>;
}

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

上面代码的游乐场链接

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

标签: rust

解决方案


推荐阅读