我试图了解getter 类型函数&和重复代码的问题&mut。我试图了解在unsafe块内使用强制转换来解决此问题的特定解决方案是否安全。
以下是该问题的一个示例。它取自非常好的教程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
})
}
}
Run Code Online (Sandbox Code Playgroud)
在我看来,您可以在unsafe块中使用强制转换来解决此问题。该解决方案似乎具有以下属性:
以下是解决方案:
// 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())
}
}
Run Code Online (Sandbox Code Playgroud)
这些是我认为它看起来安全的理由:
peek() is from a known source with a known alias situation.&mut self there are no refs to its elements.peek() in unaliased.peek() does not escape this function body.& to &mut doesn't seem to violate the pointer aliasing rules.The same problem is discussed the following question: How to avoid writing duplicate accessor functions for mutable and immutable references in Rust?
This question is different because it asks about details of one specific solution to the problem.
There are other kinds of solutions to the problem, such as this one: Abstracting over mutability in Rust
But all other solutions seem to introduce quite a bit of extra complexity to the code.
The Nomicon asserts strongly that it is always undefined behaviour to cast & to &mut, which implies that this solution is not safe. But it makes no attempt whatsoever to explain why.
The Rust Reference states that "Breaking the pointer aliasing rules" is UB. To me it seems like this solution doesn't do that, for reasons given above.
I have the following questions to people with deeper Rust knowledge than myself:
peek_mut safe?我相信这段代码会调用未定义的行为。引用Nomicon:
- 将 & 转换为 &mut 是 UB
- 将 & 转换为 &mut 始终是 UB
- 不,你不能这样做
- 不,你并不特别
更重要的是,Rust 编译器会将peek()LLVM 中间表示中的返回值标记为不可变,并且 LLVM 可以根据此断言自由进行优化。在这种特定情况下目前可能不会发生,但我仍然认为这是未定义的行为。如果你想不惜一切代价避免重复,你可以使用宏。
| 归档时间: |
|
| 查看次数: |
168 次 |
| 最近记录: |