我试图了解 &
的重复代码的问题和 &mut
在 getter 类型的函数中。我试图了解是否使用 unsafe
中的强制转换来解决此问题的特定解决方案 block 将是安全的。
以下是该问题的一个示例。它取自非常好的教程
Learning Rust With Entirely Too Many Linked Lists .
type Link<T> = Option<Box<Node<T>>>;
pub struct List<T> {
head: Link<T>,
}
struct Node<T> {
elem: T,
next: Link<T>,
}
impl<T> List<T> {
// Other methods left out...
// The implementation of peek is simple, but still long enough
// that you'd like to avoid duplicating it if that is possible.
// Some other getter-type functions could be much more complex
// so that you'd want to avoid duplication even more.
pub fn peek(&self) -> Option<&T> {
self.head.as_ref().map(|node| {
&node.elem
})
}
// Exact duplicate of `peek`, except for the types
pub fn peek_mut(&mut self) -> Option<&mut T> {
self.head.as_mut().map(|node| {
&mut node.elem
})
}
}
解决方案
在我看来,您可以在
unsafe
中使用类型转换。 block 来解决这个问题。该解决方案似乎具有以下属性:以下是解决方案:
// Implemention of peek_mut by casting return value of `peek()`
pub fn peek_mut(&mut self) -> Option<&mut T> {
unsafe {
std::mem::transmute(self.peek())
}
}
这些是为什么我认为它似乎安全的论点:
peek()
的返回值来自具有已知别名情况的已知来源。 &mut self
它的元素没有引用。 peek()
的返回值在无别名。 peek()
的返回值不会转义这个函数体。 &
至&mut
似乎没有违反指针别名规则。 杂项说明
这个问题是不同的,因为它询问问题的一个特定解决方案的细节。
但是所有其他解决方案似乎都给代码带来了相当多的额外复杂性。
&
始终是未定义的行为。至&mut
,这意味着该解决方案不安全。但它没有试图解释原因。 问题
对于 Rust 知识比我自己更深的人,我有以下问题:
peek_mut
的提供的实现吗?安全的? 最佳答案
我相信这段代码会调用未定义的行为。报价 the Nomicon :
- Transmuting an & to &mut is UB
- Transmuting an & to &mut is always UB
- No you can't do it
- No you're not special
更重要的是,Rust 编译器会标记
peek()
的返回值。在 LLVM 中间表示中是不可变的,并且 LLVM 可以根据此断言自由进行优化。在这种特定情况下目前可能不会发生,但我仍然认为这是未定义的行为。如果您想不惜一切代价避免重复,您可以使用宏。
关于rust - 使用强制转换的可变访问器是否安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59594870/