在 Rust 1.36 中,编译如下:
let arr = [0 as u8; 30];
let buf: Box<[u8]> = Box::new(arr);
Run Code Online (Sandbox Code Playgroud)
但这失败了,并出现错误:expected slice, found array of 30 elements引用带下划线的代码:
let arr = [0 as u8; 30];
let buf: RefCell<[u8]> = RefCell::new(arr);
^^^^^^^^^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)
谁能解释为什么行为不同?和RefCell都Box将 T 约束为<T: ?Sized>。
Box<T>实现该特征CoerceUnsized<U>,该特征允许在实现该特征时从 强制转换Box<T>为。直观地说,实现if是 的“未调整大小”版本。例如,实现并在实现时实现。Box<U>TUnsize<U>TUnsize<U>UT[T; N]Unsize<[T]>TUnsize<dyn Trait>TTrait
impl<T, U> CoerceUnsized<Box<U>> for Box<T> where
T: Unsize<U> + ?Sized,
U: ?Sized,
Run Code Online (Sandbox Code Playgroud)
RefCell<T>也实现了CoerceUnsized<U>,但实现更加有限。如果已经可以强制到,它只能执行从RefCell<T>到 的强制转换,其中不包括。RefCell<U>TUT: Unsize<U>
impl<T, U> CoerceUnsized<RefCell<U>> for RefCell<T> where
T: CoerceUnsized<U>,
Run Code Online (Sandbox Code Playgroud)
这里的原因是后面的强制CoerceUnsized<U>应该总是在指针后面。这适用于Box<T>,但不适用于RefCell<T>。RefCell<T>尽管被称为参考单元,但实际上直接保存其数据。RefCell<T>有字段value: UnsafeCell<T>并且UnsafeCell<T>只有一个字段value: T。这里没有发生间接的情况。
碰巧的是, 的规则确实Unsize<U>允许RefCell<T>: Unsize<RefCell<U>>when T: Unsize<U>,因此如果我们隐藏在指针后面,我们可以在它们之间进行强制。
use std::cell::RefCell;
fn main() {
let _: &mut RefCell<[u8]> = &mut RefCell::new([0; 30]);
}
Run Code Online (Sandbox Code Playgroud)
其他(智能)指针也可以在这里工作。Box<T>、Rc<T>等(游乐场链接)
| 归档时间: |
|
| 查看次数: |
393 次 |
| 最近记录: |