use std::collections::{HashMap, HashSet};
pub struct P<'a> {
x: &'a str
}
pub struct Foo<'a, T> {
callbacks: Vec<Box<'a + FnMut(&T)>>
}
impl<'a, T> Foo<'a, T>{
pub fn foo(&mut self, payload: T) {
}
}
pub struct Foo2<'a> {
callbacks: Vec<Box<'a + FnMut(&P)>>
}
impl<'a> Foo2<'a>{
pub fn foo(&mut self, payload: P) {
}
}
struct Bar<'a, 'b> {
x: Foo<'a, P<'b>>,
y: Foo2<'a>,
data: HashMap<String, String>
}
impl<'a, 'b> Bar<'a, 'b> {
// fn test(&mut self) {
// // Cannot infer an appropriate lifetime.
// match self.data.get("foo") {
// Some(x) => {
// let p = P {x};
// self.x.foo(p);
// },
// None => {}
// }
// }
fn test2(&mut self) {
match self.data.get("foo") {
Some(x) => {
let p = P {x};
self.y.foo(p);
},
None => {}
}
}
}
Playground。我每晚都在使用rustc 1.19.0。
为什么test2
有效但test
没有?如何正确制作通用结构Foo
?
我认为此示例不涉及Why can't I store a value and a reference to that value in the same struct?,并且不重复。
答案 0 :(得分:2)
什么是'a
,什么是'b
?
如果我们找出失败的案例(请注意我为self
引入了一段时间以使其更容易):
pub struct P<'a> {
x: &'a str
}
pub struct Foo<'a, T> {
callbacks: Vec<Box<'a + FnMut(&T)>>
}
impl<'a, T> Foo<'a, T>{
pub fn foo(&mut self, payload: T) {
}
}
struct Bar<'a, 'b> {
x: Foo<'a, P<'b>>,
data: HashMap<String, String>
}
impl<'a, 'b> Bar<'a, 'b> {
fn test<'c>(&'c mut self) {
// Cannot infer an appropriate lifetime.
match self.data.get("foo") {
Some(x) => {
let p = P {x};
self.x.foo(p);
},
None => {}
}
}
}
这里的问题是当您实例化 Bar
时,您修复 'a
和'b
是什么。
具体来说,这个生命周期不是'c
,这完全不相关。
编译器看到:
self.x.foo
的参数必须为P<'b>
,P<'unknown>
,其中'unknown
的任何生命周期少于而不是'c
,P<'unknown>
,因此'unknown
必须大于'b
,'b
和'c
无关。并且不知道'unknown
应该是什么。
可能的解决方案是避免修复'b
:
pub struct Foo<'a> {
callbacks: Vec<Box<'a + FnMut(&P)>>,
}
impl<'a> Foo<'a> {
pub fn foo(&mut self, payload: P) {}
}
struct Bar<'a> {
x: Foo<'a>,
data: HashMap<String, String>,
}
注意:此时,'a
似乎也是多余的。
然而,这需要我们修复T
,因为当使用类型参数(就像我们使用Foo<'a, T>
时)时,我们需要完全指定类型,从而命名{{{ 1}}将包含。