&mut self 被推断为'static生命周期时的 Rust 生命周期问题
咱们先把这个问题的根源捋明白,再看怎么解决。
首先看报错的核心原因:你定义的全局静态变量G是RwLock<Option<X<Item>>>,这里的Item没有显式指定生命周期参数,Rust会默认把它推断为'static——也就是说G里存的其实是X<Item<'static>>。而你原来的my_fn方法,Rust会默认做这样的生命周期推断:
fn my_fn<'a>(&'a mut self, _s: &'a K) { ... }
它把&mut self的生命周期和_s的生命周期绑定成了同一个'a。因为self来自全局静态变量,'a就被推断成了'static,可你传入的&Item::Option(s.as_str())里的字符串引用是绑定到函数f里的局部变量s的,s在函数结束就会被销毁,生命周期远短于'static,这就导致了编译器的报错。
你的核心需求很明确:既要修改self(所以必须保留&mut self),又要告诉编译器——我不会把传入的_s存储到self里,它的生命周期不需要和self绑定。那解决方法就是给my_fn显式指定独立的生命周期参数,打破这种默认的绑定。
修改后的代码如下:
use std::sync::RwLock; enum Item<'a> { Option(&'a str), } struct X<K> { v: u8, i: K, } impl<K> X<K> { // 显式声明两个独立的生命周期:'a对应_s,'b对应self fn my_fn<'a, 'b>(&'b mut self, _s: &'a K) { self.v = 0; } } static G: RwLock<Option<X<Item>>> = RwLock::new(None); fn f(s: String) { let mut v = G.write().unwrap(); let v = v.as_mut().unwrap(); v.my_fn(&Item::Option(s.as_str())); }
这样修改后,编译器就明白&mut self的生命周期'b和_s的生命周期'a没有关联,my_fn只是临时使用_s,不会把它的引用存到self里,也就不会要求s的生命周期必须是'static了。
另外补充一下:为什么去掉mut问题就消失?因为当self是&self(不可变引用)时,Rust的生命周期推断规则会允许_s的生命周期短于self——毕竟不可变引用允许多个别名,编译器不需要强制它们生命周期一致。但可变引用的默认推断是严格绑定的,所以必须显式拆分生命周期来解决这个问题。
备注:内容来源于stack exchange,提问作者aav

