This question already has answers here:
Is it possible to create a RefCell<Any>?

(2 个回答)


1年前关闭。




在 Rust 1.36 中,编译如下:
let arr = [0 as u8; 30];
let buf: Box<[u8]> = Box::new(arr);

但是这个失败了,错误是:expected slice, found array of 30 elements 指的是带下划线的代码:
let arr = [0 as u8; 30];
let buf: RefCell<[u8]> = RefCell::new(arr);
                         ^^^^^^^^^^^^^^^^^

谁能解释为什么行为不同? RefCellBox 都将 T 约束为 <T: ?Sized>

最佳答案

Box<T> 实现了 the trait CoerceUnsized<U> ,它允许在 Box<T> 实现 the trait Box<U> 时从 T 强制转换为 Unsize<U> 。直观地说,如果 TUnsize<U> 的“未调整大小”版本,则 U 实现了 T。例如,当 [T; N] 实现 Unsize<[T]> 时,T 实现 Unsize<dyn Trait>T 实现 Trait

impl<T, U> CoerceUnsized<Box<U>> for Box<T> where
    T: Unsize<U> + ?Sized,
    U: ?Sized,
RefCell<T> 也实现了 CoerceUnsized<U> ,但有一个更有限的实现。如果 RefCell<T> 已经可以被强制转换为 RefCell<U> ,则它只能执行从 TU 的强制转换,其中不包括 T: Unsize<U>
impl<T, U> CoerceUnsized<RefCell<U>> for RefCell<T> where
    T: CoerceUnsized<U>,

这里的原因是 CoerceUnsized<U> 后面的强制转换应该总是在一个指针后面。这适用于 Box<T> ,但不适用于 RefCell<T>RefCell<T> 尽管被称为 Ref Cell,但实际上直接保存其数据。 RefCell<T> 有字段 value: UnsafeCell<T>UnsafeCell<T> 只有一个字段 value: T 。这里没有间接进行。

碰巧的是,Unsize<U> 的规则确实允许 RefCell<T>: Unsize<RefCell<U>>T: Unsize<U> 时,所以如果我们隐藏在指针后面,我们可以在它们之间进行强制。
use std::cell::RefCell;

fn main() {
    let _: &mut RefCell<[u8]> = &mut RefCell::new([0; 30]);
}

其他(智能)指针也可以在这里工作。 Box<T>Rc<T> 等。 (playground link)

关于rust - Box<T> 和 RefCell<T> 构造函数之间的行为差​​异,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57563768/

10-12 06:54