///////// third lib /////////////
struct ThirdPartPage<'a> {
name: &'a str,
content: &'a str
}
struct ThirdPartDoc<'a> {
page: ThirdPartPage<'a>
}
impl <'a> ThirdPartDoc<'a> {
fn get_page(&self) -> &ThirdPartPage<'a> {
&self.page
}
}
///////// resource //////////
trait ResourceTrait<'a> {
fn get_content(&self) -> &str;
}
struct TirdpartResource<'a> {
data: &'a ThirdPartPage<'a>
}
impl<'a> ResourceTrait<'a> for TirdpartResource<'a> {
fn get_content(&self) -> &str {
self.data.content
}
}
////////// main logic ////////
struct Owner<'a> {
doc: Option<ThirdPartDoc<'a>>
}
impl<'a> Owner<'a> {
fn get_resource(&self) -> Option<Box<dyn ResourceTrait<'a>>> {
match &self.doc {
Some(doc) => {
Some(Box::new(TirdpartResource {
data: doc.get_page()
}))
},
None => Option::None
}
}
}
fn main() {
let owner = Owner {
doc: Some(ThirdPartDoc {
page: ThirdPartPage {
name: "page",
content: "content"
}
})
};
let res = owner.get_resource();
println!("{}", res.unwrap().get_content());
}
third lib是外部库,这里是错误信息:
Compiling playground v0.0.1 (/playground)
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
--> src/main.rs:42:15
|
42 | match &self.doc {
| ^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime defined on the method body at 41:21...
--> src/main.rs:41:21
|
41 | fn get_resource(&self) -> Option<Box<dyn ResourceTrait<'a>>> {
| ^^^^^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:42:15
|
42 | match &self.doc {
| ^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 40:6...
--> src/main.rs:40:6
|
40 | impl<'a> Owner<'a> {
| ^^
note: ...so that the types are compatible
--> src/main.rs:44:22
|
44 | Some(Box::new(TirdpartResource {
| ______________________^
45 | | data: doc.get_page()
46 | | }))
| |__________________^
= note: expected `ResourceTrait<'a>`
found `ResourceTrait<'_>`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0495`.
error: could not compile `playground`
To learn more, run the command again with --verbose.
1
共 1 条评论, 1 页
评论区
写评论分析
get_resource
这个函数:get_resource(&self)
: 函数接受一个参数,类型是Self
也即Owner<'a>
的引用,这个引用的生命周期是隐式的,我们姑且记为'_
,所以函数的实际签名是get_resource(&'_ self)
match &self.doc
: 从self
里借走了doc
,那么这个借的周期是什么呢,在这个节点,编译器只知道这个周期需要不短于match
的block,不长于'_
,假设这个周期是'b
Some(Box::new(TirdpartResource { data: doc.get_page() }))
:doc.get_page()
拿了一个生命周期'b
的&ThirdPartDoc<'a>
,返回一个&'b ThirdPartPage<'a>
用来构造TirdpartResource
。虽然看起来TirdpartResource<'a>
是说这个结构里的所有周期都必须是'a
,但其实'a
是泛型参数,所以编译器只需要选取输入生命周期中最局限的生命周期就可以了,假定这个生命周期是'c
,我们知道的是'c
必须不长于'b
和'a
现在来推断一下生命周期。
'c
不长于'b
不长于'_
,但是同时根据返回值类型匹配,'c='a
,所以'a
必须不长于'_
,但是从函数签名中无法保证这一点,所以无法编译。另一种解读的方法就是,根据前者'b
应当设定为'_
,但后者表明'b
应当设定为'a
,产生了矛盾。那么如何修复,只需要保证
'_
不短于'a
就可以了,这里还有个需要注意的小问题,就是Box
这种堆上内存的生命周期需要显式标注。方案1 让
'_='a
:方案2 让
'_ >= 'a
: