调用Trait中返回引用类型的函数时编译错误:借用值生命周期不足
Rust生命周期错误解析:
bundle未存活足够久的问题 我是Rust新手,编写了以下代码后遇到编译器错误,我认为format!()执行后就不再借用bundle了,但rustc却提示它“仍被借用”,想了解原因:
复现代码
use std::rc::Rc; trait Bundle<'a> { fn id(&'a self) -> &'a str; } struct Demo { id: String, } impl<'a> Bundle<'a> for Demo { fn id(&'a self) -> &'a str { &self.id } } fn x(bundle: Rc<dyn Bundle<'_>>, file: &str) -> String { let id = bundle.id(); format!("bundle/{}/{}", id, file) } fn main() { let demo = Rc::new(Demo { id: String::from("demo"), }); println!("{}", x(demo as Rc<dyn Bundle>, "hello.txt")); }
编译器错误
error[E0597]: `bundle` does not live long enough --> src/main.rs:18:14 | 17 | fn x(bundle: Rc<dyn Bundle<'_>>, file: &str) -> String { | ------ has type `Rc<dyn Bundle<'1>>` 18 | let id = bundle.id(); | ^^^^^^^^^^^ | | | borrowed value does not live long enough | argument requires that `bundle` is borrowed for `'1` 19 | format!("bundle/{}/{}", id, file) 20 | } | - `bundle` dropped here while still borrowed
问题原因与解决方法
核心原因
你的trait定义把生命周期参数'a绑定在了trait本身上,并且id方法要求&'a self,这意味着返回的&str引用的生命周期必须和trait的'a参数完全绑定,而不是和方法调用时的self临时引用生命周期一致。
当你把Rc<Demo>转成Rc<dyn Bundle>时,编译器会推断出一个生命周期'1,这个'1实际对应Demo实例(也就是main里的demo)的生命周期。但在fn x中,bundle作为函数参数,它的生命周期只到函数结束(第20行)。调用bundle.id()时,方法要求bundle必须被借用整个'1周期(也就是和main里的demo一样久),但bundle在函数结束就会被销毁,这就产生了生命周期冲突——编译器认为你试图让一个局部变量的借用生命周期超过它本身的存活时间。
修复方案
调整trait的定义,把生命周期绑定在方法上而不是trait本身:
use std::rc::Rc; // 移除trait上的生命周期参数 trait Bundle { // 方法的引用生命周期和&self自动绑定 fn id(&self) -> &str; } struct Demo { id: String, } impl Bundle for Demo { fn id(&self) -> &str { &self.id } } fn x(bundle: Rc<dyn Bundle>, file: &str) -> String { let id = bundle.id(); format!("bundle/{}/{}", id, file) } fn main() { let demo = Rc::new(Demo { id: String::from("demo"), }); println!("{}", x(demo as Rc<dyn Bundle>, "hello.txt")); }
这样修改后,id返回的&str生命周期会自动和调用时的&self引用一致,format!会把这个引用转成String,不会持有原引用到函数结束,编译器就能正确推断生命周期,不会再报错。
内容的提问来源于stack exchange,提问作者Eric
相关产品推荐
相关产品推荐

