当前版本的Rustonomicon具有以下示例代码:
use std::mem;
pub struct IterMut<'a, T: 'a>(&'a mut [T]);
impl<'a, T> Iterator for IterMut<'a, T> {
type Item = &'a mut T;
fn next(&mut self) -> Option<Self::Item> {
let slice = mem::replace(&mut self.0, &mut []);
if slice.is_empty() {
return None;
}
let (l, r) = slice.split_at_mut(1);
self.0 = r;
l.get_mut(0)
}
}
我对这条线特别感到困惑:
let slice = mem::replace(&mut self.0, &mut []);
// ^^^^^^^
该借贷如何检查?如果这是不可变的借项,则RFC 1414指示[]
右值应具有'static
生存期,以便不可变的借项将进行借阅检查,但该示例显示了可变借项!似乎必须进行以下两项操作之一:
[]
是临时的(以便可以可变地使用),在这种情况下,它将没有'static
生命周期,并且不应借阅支票;[]
存在'static
生命周期,因此应该不可能进行可变借贷(因为我们不能像借贷时那样保证独占访问权),也不应该进行借阅支票。我想念什么?
有关:
这个问题集中在不可变的引用上。这个问题是关于可变参考。
这个问题的重点是在函数内部获取引用。这个问题是关于返回参考。
TL; DR:空数组在编译器中是特殊情况,它是安全的,因为您永远无法取消引用零长度数组的指针,因此不会发生可变别名。
RFC 1414(右值静态提升)讨论了将值提升为static
值的机制。它有一章介绍了可变引用的可能扩展(bolting mine):
&'static mut
只要存在附加约束,即所引用的类型为零大小,就可以扩展对引用的支持。这在数组引用构造函数中再次具有优先级:
// valid code today let y: &'static mut [u8] = &mut [];
规则将类似:
- 如果采用对constexpr rvalue的可变引用。(
&mut <constexpr>
)- 而且constexpr不包含
UnsafeCell { ... }
构造函数。- 而且constexpr不包含const fn调用,该调用返回包含的类型
UnsafeCell
。- 右值的类型为零。
- 然后,不要将值转换为堆栈插槽,而是将其转换为静态内存位置并为生成的引用提供
'static
生命周期。零大小的限制之所以存在,是因为别名可变引用仅对零大小的类型是安全的(因为您从未为它们取消引用指针)。
由此可见,在编译器中当前对空数组的可变引用是特殊情况的。在锈1.39,所讨论的分机已没有得到落实:
struct Zero;
fn example() -> &'static mut Zero {
&mut Zero
}
error[E0515]: cannot return reference to temporary value
--> src/lib.rs:4:5
|
4 | &mut Zero
| ^^^^^----
| | |
| | temporary value created here
| returns a reference to data owned by the current function
虽然阵列版本确实有效:
fn example() -> &'static mut [i32] {
&mut []
}
也可以看看:
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句