为什么可以从函数返回对文字的可变引用? [英] Why is it possible to return a mutable reference to a literal from a function?

查看:56
本文介绍了为什么可以从函数返回对文字的可变引用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

The Rustonomicon 有这个示例代码:

The current edition of The Rustonomicon has this example code:

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)
    }
}

我特别对这条线感到困惑:

I'm confused about this line in particular:

let slice = mem::replace(&mut self.0, &mut []);
//                                    ^^^^^^^ 

这个借阅如何检查?如果这是一个不可变的借用,RFC 1414 表示 [] 右值应该有 'static 生命周期,这样一个不可变借用会借用检查,但这个例子显示了一个可变借用!似乎必须发生两件事之一:

How does this borrow check? If this were an immutable borrow, RFC 1414 indicates that the [] rvalue should have 'static lifetime, so that an immutable borrow would borrow-check, but the example shows a mutable borrow! It seems that one of two things must be going on:

  • 要么 [] 是临时的(以便它可以可变地使用),在这种情况下它没有 'static 生命周期,并且不应该借用检查;
  • 或者 [] 具有 'static 生命周期,因此它不应该可以进行可变借用(因为我们不保证独占访问)借用),不应借用检查.
  • Either [] is a temporary (so that it can be used mutably), in which case it would not have 'static lifetime, and should not borrow-check;
  • Or that [] has 'static lifetime, and therefore it should not be possible to take a mutable borrow (since we don't guarantee exclusive access as we take the borrow), and should not borrow-check.

我错过了什么?

相关:

这个问题关注的是不可变引用;这个问题是关于可变引用的.

This question focuses on immutable references; this question is about mutable references.

为什么临时借用是合法的?

这个问题的重点是在函数内部获取引用;这个问题是关于返回一个参考.

This question focuses on taking references inside of a function; this question is about returning a reference.

推荐答案

TL;DR:空数组在编译器中是特殊情况,它是安全的,因为你永远不能解引用零长度数组的指针,所以有没有可能的可变别名.

TL;DR: empty arrays are special cased in the compiler and it's safe because you can't ever dereference the pointer of a zero-length array, so there's no possible mutable aliasing.

RFC 1414,右值静态提升,讨论了其机制值被提升为 static 值.它有一个关于可变引用(加粗我的):

RFC 1414, rvalue static promotion, discusses the mechanism by which values are promoted to static values. It has a section about possible extensions for mutable references (bolding mine):

可以扩展对 &'static mut 引用的支持,只要有额外的约束引用类型的大小为零.

It would be possible to extend support to &'static mut references, as long as there is the additional constraint that the referenced type is zero sized.

这再次在数组引用构造函数中具有优先权:

// valid code today
let y: &'static mut [u8] = &mut [];

规则类似:

  • 如果采用对 constexpr 右值的可变引用.(&mut )
  • 并且 constexpr 不包含 UnsafeCell { ... } 构造函数.
  • 并且 constexpr 不包含返回包含 UnsafeCell 的类型的 const fn 调用.
  • 右值的类型为零.
  • 然后不是将值转换到堆栈槽中,而是转换将它放入一个静态内存位置,并给结果引用一个'static 生命周期.
  • If a mutable reference to a constexpr rvalue is taken. (&mut <constexpr>)
  • And the constexpr does not contain a UnsafeCell { ... } constructor.
  • And the constexpr does not contain a const fn call returning a type containing a UnsafeCell.
  • And the type of the rvalue is zero-sized.
  • Then instead of translating the value into a stack slot, translate it into a static memory location and give the resulting reference a 'static lifetime.

零尺寸限制是因为别名可变引用仅对零大小类型安全(因为您从不为它们取消引用指针).

由此,我们可以看出对空数组的可变引用目前在编译器中是特殊情况.在 Rust 1.39 中,讨论的扩展没有被实现:

From this, we can tell that mutable references to empty arrays are currently special-cased in the compiler. In Rust 1.39, the discussed extension has not been implemented:

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

虽然阵列版本确实有效:

While the array version does work:

fn example() -> &'static mut [i32] {
    &mut []
}

另见:

这篇关于为什么可以从函数返回对文字的可变引用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆