rust - 实现一个 trait 方法,为拥有的类型返回一个有界的生命周期引用

标签 rust traits lifetime borrowing

假设我有这个结构和这个特征:

#[derive(Debug)]
pub struct New<T>(T);

pub trait AsRefNew<'a> {
    fn as_ref(&self) -> New<&'a str>;
}
也就是说,AsRefNew trait 允许返回具有给定生命周期的引用 'a包裹在 New新型。此生'a可能与 &self 的生命周期不同(并且将会不同)范围。
现在我可以为 New(&str) 实现这个特征, 并使其输出的生命周期是包装的 &str 的生命周期:
impl<'a> AsRefNew<'a> for New<&'a str> {
    fn as_ref(&self) -> New<&'a str>{
        New(self.0)
    }
}
我的问题是我想实现 New(String) 的特征,而这一次,我想要 'a实际匹配 self 的生命周期.我的理解是这样的事情应该有效:
impl<'a> AsRefNew<'a> for New<String> where Self: 'a{
    fn as_ref(&self) -> New<&'a str> {
        New(self.0.as_str())
    }
}
除非它没有:
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
  --> src/main.rs:16:20
   |
16 |         New(self.0.as_str())
   |                    ^^^^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 15:5...
  --> src/main.rs:15:5
   |
15 |     fn as_ref(&self) -> New<&'a str> {
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that reference does not outlive borrowed content
  --> src/main.rs:16:13
   |
16 |         New(self.0.as_str())
   |             ^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 14:6...
  --> src/main.rs:14:6
   |
14 | impl<'a> AsRefNew<'a> for New<String> where Self: 'a{
   |      ^^
note: ...so that the expression is assignable
  --> src/main.rs:16:9
   |
16 |         New(self.0.as_str())
   |         ^^^^^^^^^^^^^^^^^^^^
   = note: expected `New<&'a str>`
              found `New<&str>`

我尝试了生命周期和泛型的不同变体,但我找不到更好的方式来表达我在这种情况下想要 'a 的事实。匹配 '_ .
目标是让这个片段工作:
fn main() {
    // This works:
    let a = String::from("Hey");
    let b;
    {
        let c = New(a.as_str());
        b = c.as_ref().0;
    }
    println!("{:?}", b);
    
    // I would like that to work as well:
    let a = String::from("Ho");
    let b;
    let c = New(a);
    {
        b = c.as_ref().0;
    }
    println!("{:?}", b);
}
有任何想法吗 ?

最佳答案

正如 Sven 所解释的,为了使这项工作正常进行,我们需要两个不同的方法原型(prototype),而 AsRefNew 无法做到这一点。被定义的特征。
尽管如此,它可以被修改以使小片段工作,例如在签名中引入第二个生命周期:

#[derive(Debug)]
pub struct New<T>(T);

pub trait AsRefNew<'b, 'a> {
    fn as_ref(&'b self) -> New<&'a str>;
}

impl<'a> AsRefNew<'_, 'a> for New<&'a str> {
    fn as_ref(&self) -> New<&'a str>{
        New(self.0)
    }
}

impl<'b, 'a> AsRefNew<'b, 'a> for New<String> where 'b:'a {
    fn as_ref(&'b self) -> New<&'a str> {
        New(self.0.as_str())
    }
}

impl<T> New<T> {
    pub fn test<'b, 'a>(&'b self) -> New<&'a str> where Self: AsRefNew<'b, 'a> {
        self.as_ref()
    }
}
以下代码段现在有效:
fn main() {
    // This works:
    let a = String::from("Hey");
    let b;
    {
        let c = New(a.as_str());
        b = c.as_ref().0;
    }
    println!("{:?}", b);
    
    // It now works
    let a = String::from("Ho");
    let b;
    let c = New(a);
    {
        b = c.as_ref().0;
    }
    println!("{:?}", b);
}
New 上的方法的通用实现也是如此。类型:
impl<T> New<T> {
    pub fn test<'b, 'a>(&'b self) -> New<&'a str> where Self: AsRefNew<'b, 'a> {
        self.as_ref()
    }
}
现在唯一的问题是签名 super 难看!我想知道这是否可以通过 gats 变得更简单。

关于rust - 实现一个 trait 方法,为拥有的类型返回一个有界的生命周期引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65943869/

相关文章:

struct - 在 Rust 中调用存储在结构中的堆栈分配闭包

rust - 无法为实现我拥有的特征的所有类型实现我不拥有的特征

struct - 为什么我不能多次调用变异函数?

rust - 如何临时从结构中借用引用?

rust - 为什么通过移动捕获Arc会使我的关闭 FnOnce 而不是 Fn

multithreading - 为什么不为包含Arc的结构实现Send?

scala - 如何订购密封性状?

generics - 特征上的链接函数

rust - 什么时候在结构中定义多个生命周期有用?

arguments - 是否可以根据参数计算 Rust 函数或特征方法的返回类型?