为什么可以从函数返回对文字的可变引用?

艾丹·库利|

当前版本的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生命周期,因此应该不可能进行可变借贷(因为我们不能像借贷时那样保证独占访问权),也不应该进行借阅支票。

我想念什么?

有关:

Shepmaster

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] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

为什么我可以返回对函数拥有值的引用?

当Rust中的函数需要可变引用时,为什么不变引用可以匹配?

为什么我可以返回对本地文字的引用,而不是对变量的引用?

函数什么时候可以返回引用?

为什么以SCALAR返回函数的引用

当返回对范围外的值的可变引用的不可变引用时,为什么在范围结束时丢弃了可变引用?

为什么可以从函数中返回“向量”?

在Perl中,为什么不能祝福一个包含对文字的引用的变量?

将可变数组引用传递到也需要可变数组引用的函数中时,为什么不声明&mut?

为什么Rust无法在类型构造函数中将可变引用强制转换为不可变引用?

为什么我可以返回对对象的引用?

为什么我可以修改const按引用返回?

为什么我们使用通过引用返回的函数

为什么函数可以返回函数本身

为什么我不能从闭包中返回对外部变量的可变引用?

为什么Rust阻止了多个可变引用?

为什么您可以借用可变的引用并仍然使用两者?

为什么 Rust 不可变引用可以调用 &mut self 方法?

为什么我可以使用可变变量,使其寿命与不可变引用重叠,但是我不能以相同方式使用可变引用?

当可以对该变量进行可变引用时,为什么不能使用该可变变量?

为什么闭包的可变引用参数没有超过函数调用的寿命?

为什么C ++中的函数可以返回堆栈值

为什么我可以在函数后返回“ int”而不是“ char *”?

为什么 c++ 函数可以正确返回数组的大小?

为什么通过通用引用运算符 (&&) 将变量的引用传递给可变参数模板函数失败?

不能在不可变值上使用可变成员:函数调用返回不可变值 - 不确定为什么值是不可变的

如果使用返回引用的函数初始化'auto'var,为什么不声明引用类型?

为什么返回对象的JavaScript函数通过引用(引用其参数)来实现?

元组为什么可以包含可变项?