Rust生命周期显性非关联性问题:寻求无注解解决方案
解决Rust中Vector/Matrix trait的生命周期错误
先看你的最小可复现代码:
trait Vector { type T; fn get(&self, i: usize) -> &Self::T; } trait Matrix { type F; fn get(&self, i: usize, j: usize) -> &Self::F; } struct MyMatrix<C>(C); impl<C: Vector<T=R>, R: Vector<T=F>, F> Matrix for MyMatrix<C> { type F = F; fn get(&self, i: usize, j: usize) -> &Self::F { // ERROR: the parameter type `R` may not live long enough self.0.get(i).get(j) } }
对应的编译错误:
error[E0311]: the parameter type `R` may not live long enough --> playground/src/main.rs:20:9 | 16 | fn get(&self,i:usize,j:usize) -> &Self::F { | ----- the parameter type `R` must be valid for the anonymous lifetime defined here... ... 20 | / self.0 21 | | .get(i) | |___________________^ ...so that the type `R` will meet its required lifetime bounds | help: consider adding an explicit lifetime bound | 16 | fn get<'a>(&'a self,i:usize,j:usize) -> &'a Self::F where R: 'a { | ++++ ++ ++ +++++++++++
错误原因
编译器的担忧在于:R作为C的关联类型,可能本身包含引用(比如R是&'a [i32])。如果R内部的引用生命周期短于self(当前MyMatrix实例的生命周期),那么调用self.0.get(i)得到的&R会指向一个生命周期不足的类型,后续从R中获取的元素引用就会悬空。虽然Vector::get保证返回的引用和输入的&self同生命周期,但编译器无法自动推断R的生命周期约束必须覆盖self的生命周期。
无需全局修改的解决方案
不需要改动原有的trait结构,也不用给整个库加生命周期注解,只需要在impl的约束中给R添加一个匿名生命周期约束,明确R的所有引用生命周期都不短于self的生命周期:
trait Vector { type T; fn get(&self, i: usize) -> &Self::T; } trait Matrix { type F; fn get(&self, i: usize, j: usize) -> &Self::F; } struct MyMatrix<C>(C); // 修改impl的约束,添加R: '_ impl<C, R, F> Matrix for MyMatrix<C> where C: Vector<T = R>, R: Vector<T = F> + '_', // 关键:告诉编译器R的生命周期不短于self F: ?Sized, { type F = F; fn get(&self, i: usize, j: usize) -> &Self::F { self.0.get(i).get(j) } }
为什么这个方案有效
R: '_中的'_代表当前上下文的匿名生命周期(也就是self的生命周期),这个约束要求R类型中包含的所有引用的生命周期都至少和self一样长。这样编译器就能确定:从R中获取的元素引用,其生命周期可以安全地和self的生命周期绑定,不会出现悬空引用的问题。
这个改动非常局部,只影响MyMatrix的Matrix实现,不会对库的其他部分造成侵入式修改,完美保留了你原有的trait和结构体结构。
内容的提问来源于stack exchange,提问作者user35593
相关产品推荐
相关产品推荐

