P.UNS.SAS.08 函数参数是不可变借用的时候,返回值不应该是可变借用
【描述】
即便函数签名中没有 unsafe
,但开发者无法保证它函数头部实现中不含 Unsafe代码。
当通过 Unsafe 安全抽象一个函数的时候,要注意符合规则中描述的签名约定:不能输入一个不可变借用,返回一个可变的,这是违反 Rust安全准则的。
当然,当函数被标识为 unsafe
时,是允许这种情况的。
【反例】
这个来自 Rust 官方的一个示例,这样的签名导致 Rust 出现了一个严重 bug,来源
#![allow(unused)] fn main() { // 该函数未加 unsafe,被认为是安全的 // 但是函数签名违反了 Rust 的安全规则,不应该不可变借用进去,可变借用返回 pub fn as_mut_slice(&self) -> &mut [T] { unsafe { slice::from_raw_parts_mut(self.ptr as *mut T, self.len()) } } }
【正例】
#![allow(unused)] fn main() { // 修正以后的代码:https://github.com/rust-lang/rust/pull/39466/files pub fn as_mut_slice(&mut self) -> &mut [T] { unsafe { slice::from_raw_parts_mut(self.ptr as *mut T, self.len()) } } }
【例外】
#![allow(unused)] fn main() { // From: https://docs.rs/crate/wasmer/2.0.0/source/src/externals/memory.rs /// Retrieve a mutable slice of the memory contents. /// /// # Safety /// /// This method provides interior mutability without an UnsafeCell. Until /// the returned value is dropped, it is undefined behaviour to read or /// write to the pointed-to memory in any way except through this slice, /// including by calling a wasm function that reads the memory contents or /// by resizing this Memory. // 这里为 unsafe 函数,则允许这种情况 #[allow(clippy::mut_from_ref)] pub unsafe fn data_unchecked_mut(&self) -> &mut [u8] { let definition = self.vm_memory.from.vmmemory(); let def = definition.as_ref(); slice::from_raw_parts_mut(def.base, def.current_length.try_into().unwrap()) } }