我想在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);
}
}
我在这里试图告诉borrow 判断器的是,当我初始化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
这意味着不知何故我的生命周期 不匹配.