定义采用更高级类型泛型的特征

问题描述 投票:0回答:1

我想在 Rust 中定义一个特征,它有一个泛型类型参数 - 例如,在特征级别的

BorrowedValue
,以及一个生命周期参数,例如在其方法级别的
'a
。复杂的是,方法参数的实际类型是这两者的组合,即
BorrowedValue<'a>
。这可能最好用代码来说明:

// Constructs a borrowed value with a specific lifetime
trait ConstructI32AsBorrowed<'a>: 'a {
    fn construct(x: &'a i32) -> Self;
}

// A struct which implements this
#[derive(Debug)]
struct BorrowedI32<'a> {
    value: &'a i32
}
impl<'a> ConstructI32AsBorrowed<'a> for BorrowedI32<'a> {
    fn construct(value: &'a i32) -> Self { Self { value } }
}

// This is the important bit
// A trait which represents BorrowedValue as a String, say in some special way
// note that the type parameter BorrowedValue exists at the trait level, but the
// lifetime 'a exists at the method level
trait ShowBorrowedValue<BorrowedValue: std::fmt::Debug> {
    fn show_debug(&self, borrowed: BorrowedValue) -> String
    where BorrowedValue: for<'a> ConstructI32AsBorrowed<'a>;
}

// Define a simple struct which implements ShowBorrowedValue by capitalizing the debug outputs
struct ShowsI32InCapitals;
impl<BorrowedValue: std::fmt::Debug> ShowBorrowedValue<BorrowedValue> for ShowsI32InCapitals {
    fn show_debug(&self, borrowed: BorrowedValue) -> String
    where BorrowedValue: for<'a> ConstructI32AsBorrowed<'a>
    {
        format!("{:?}", borrowed).to_string().to_uppercase()
    }
}

pub fn main() {
    // We have a single instance of our struct
    let shows_i32_in_capitals = ShowsI32InCapitals;
    // But we want to apply it to two different borrowed values with two different lifetimes;
    // this checks that the `'a ` lifetime argument is not fixed at the level of the struct
    {
        let val_a = BorrowedI32::construct(&0_i32);
        shows_i32_in_capitals.show_debug(val_a);
    }
    {
        let val_b = BorrowedI32::construct(&1_i32);
        shows_i32_in_capitals.show_debug(val_b);
    }
}

我在这里试图告诉借用检查器的是,当我初始化

show_i32_in_capitals
时,我很乐意修复(更高种类的)类型
BorrowedValue
- 这不会改变。但是,我不想在这里修复生命周期
'a
:我希望每当我调用
show_debug
时都可以设置它。

目前编译器给出了这个有趣的错误:

error: implementation of `ConstructI32AsBorrowed` is not general enough
  --> src/main.rs:43:9
   |
43 |         shows_i32_in_capitals.show_debug(val_a);
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `ConstructI32AsBorrowed` is not general enough
   |
   = note: `ConstructI32AsBorrowed<'0>` would have to be implemented for the type `BorrowedI32<'_>`, for any lifetime `'0`...
   = note: ...but `ConstructI32AsBorrowed<'1>` is actually implemented for the type `BorrowedI32<'1>`, for some specific lifetime `'1

这意味着我的一生没有正确匹配。

感谢您提前提供的任何帮助!还有活动结束后。

rust traits higher-kinded-types
1个回答
0
投票

我不是 Rust 生命周期方面的专家,但经过一番修改后,为我编译了以下内容:

trait ShowBorrowedValue<BorrowedValue: std::fmt::Debug> {
    fn show_debug<'a>(&'a self, borrowed: BorrowedValue) -> String
    where BorrowedValue: ConstructI32AsBorrowed<'a>;
}

// Define a simple struct which implements ShowBorrowedValue by capitalizing the debug outputs
struct ShowsI32InCapitals;
impl<BorrowedValue: std::fmt::Debug> ShowBorrowedValue<BorrowedValue> for ShowsI32InCapitals {
    fn show_debug<'a>(&'a self, borrowed: BorrowedValue) -> String
    where BorrowedValue: ConstructI32AsBorrowed<'a>
    {
        format!("{:?}", borrowed).to_string().to_uppercase()
    }
}

我认为问题是,

&self
中的
show_debug()
必须比
ConstructI32AsBorrowed<'a>
中借用的值更长寿,但
for<'a>
并不表明这一点,因为赋予
&self
的隐式生命周期与
'a
无关..

© www.soinside.com 2019 - 2024. All rights reserved.