假设我有这个结构和这个特征:
#[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/