有没有可能让泛型Rust T总是堆分配的?

ctehm74n  于 11个月前  发布在  其他
关注(0)|答案(1)|浏览(95)
use std::ops::Deref;

struct Test {
    last: &'static str,
    list: Vec<String>,
}

// This is safe because we own the value and will not modify it.
// When dropping, `last` will be dropped without freeing the memory.
impl Test {
    pub fn new(value: String) -> Self {
        Self {
            last: unsafe { std::mem::transmute(value.deref()) },
            list: vec![value],
        }
    }
    pub fn insert(&mut self, value: String) {
        self.last = unsafe { std::mem::transmute(value.deref()) };
        self.list.push(value);
    }
    pub fn last(&self) -> &str {
        self.last
    }
}

字符串
有没有可能用泛型做类似的构造,比如Test<T:Deref>?我不确定deref()是否保证任何“永久”堆地址(在我的实现的有限上下文中),或者它是否保证了?
上面的代码看起来是安全的,因为在String上调用deref()会给出一个指向堆的宽指针,并且该地址永远不会改变,除非字符串本身被更改或所有权被返回给调用者。
请注意,我需要为我的用例存储&str,而不是使用ManuallyDrop::new(unsafe { ptr::read(&value) })创建的ManuallyDrop<String>

vom3gejh

vom3gejh1#

如你所料,这不安全。
存在stable_deref_trait,它提供了StableDeref特征,应该用于这种用例。然而,this crate is known to be unsound(或者至少,以不合理的方式使用),因为,例如,它为Boxbut it is not clear whether it is okay to move a Box while there are references to it实现了StableDeref(在Stacked Borrows下,这是UB,Miri将标记它)。
如果你想100%安全,堆分配所有存储的对象,并将它们存储为*mut T不是Box<T>,因为上面提到的原因),那么你可以将它们的引用存储在同一个结构中。

相关问题