#![deny(unused_unsafe)] use unsafe_fn::{safe_body, unsafe_fn}; #[derive(Default, Clone)] struct SomeStruct { i: u32, s: String, } #[unsafe_fn] fn hello(x: u32, foo: String) -> u32 { let y: u32 = unsafe { std::mem::zeroed() }; y + x + foo.len() as u32 } #[unsafe_fn] fn plus_one(mut val: u32, _x: String) -> u32 { let y: u32 = unsafe { std::mem::zeroed() }; val += 1; y + val } #[unsafe_fn] fn take_struct( SomeStruct { mut i, s }: SomeStruct, foo @ SomeStruct { .. }: &mut SomeStruct, ) -> SomeStruct { let y: u32 = unsafe { std::mem::zeroed() }; foo.i += 1; i += foo.i; SomeStruct { i: i + y, s: s + &foo.s, } } impl SomeStruct { #[unsafe_fn] fn i_plus(&self, plus: u32) -> u32 { let y: u32 = unsafe { std::mem::zeroed() }; self.i + plus + y } #[unsafe_fn] fn i_plus_box(self: Box, plus: u32) -> u32 { unsafe { self.i_plus(plus) } } #[unsafe_fn] fn with_generic<'a, 'b, T: Clone>(&'a self, r: &'b T, _: u32, _: u32) -> (&'b T, T, &'a str) where (T, Self): Default, { let _: u32 = unsafe { std::mem::zeroed() }; (r, r.clone(), &self.s) } #[unsafe_fn] fn take_self(mut self) -> Self { let y: u32 = unsafe { std::mem::zeroed() }; self.i += 2 + y; self } #[unsafe_fn] fn new() -> SomeStruct { let _: u32 = unsafe { std::mem::zeroed() }; SomeStruct::default() } #[unsafe_fn] fn with_i(i: u32) -> Self { let _: u32 = unsafe { std::mem::zeroed() }; SomeStruct { i, ..Default::default() } } #[unsafe_fn] fn with_s(s: String) -> Self { let _: u32 = unsafe { std::mem::zeroed() }; SomeStruct { s, ..Self::default() } } } pub struct StructWithGen<'a, T>(&'a T); impl<'a, T: 'a> StructWithGen<'a, T> { #[unsafe_fn] fn new_t() -> T where T: Default, { let _: u32 = unsafe { std::mem::zeroed() }; let _: Option = None; T::default() } #[unsafe_fn] fn get_t(&self) -> T where T: Clone, { let _: u32 = unsafe { std::mem::zeroed() }; self.0.clone() } } mod some_module { #[unsafe_fn::unsafe_fn] pub(crate) fn create_vec() -> Vec { let _: u32 = unsafe { std::mem::zeroed() }; Vec::new() } #[unsafe_fn::unsafe_fn] pub fn size_plus(x: usize) -> usize { let y: usize = unsafe { std::mem::zeroed() }; x + y + std::mem::size_of::() } } #[unsafe_fn] #[no_mangle] extern "C" fn deref_ptr(ptr: *const u32) -> u32 { struct Q(u32); impl Q { fn new(i: u32) -> Self { Self(i) } } Q::new(unsafe { *ptr }).0 } #[unsafe_fn] fn with_return(x: &mut u32, cond: bool) { *x += 4; if cond { return; } *x += 8; } #[unsafe_fn] trait Marker {} unsafe impl Marker for SomeStruct {} #[test] fn test_unsafe_fn1() { assert_eq!(unsafe { hello(42, "XYZ".into()) }, 42 + 3); assert_eq!(unsafe { plus_one(42, "XYZ".into()) }, 42 + 1); let mut s1 = SomeStruct { i: 8, s: "DEF".into(), }; let s2 = unsafe { take_struct( SomeStruct { i: 5, s: "ABC".into(), }, &mut s1, ) }; assert_eq!(s1.i, 9); assert_eq!(s2.i, 5 + 9); assert_eq!(unsafe { s2.i_plus(58) }, 5 + 9 + 58); assert_eq!(unsafe { Box::new(s2.clone()).i_plus(58) }, 5 + 9 + 58); let x = 31; assert_eq!(unsafe { s2.with_generic(&x, 5, 8) }, (&x, x, "ABCDEF")); assert_eq!(unsafe { s2.take_self() }.i, 5 + 9 + 2); let _ = unsafe { some_module::create_vec::() }; assert_eq!(unsafe { some_module::size_plus::(1) }, 4 + 1); assert_eq!(unsafe { deref_ptr(&x) }, 31); let mut m = 1; unsafe { with_return(&mut m, true) }; assert_eq!(m, 1 + 4); } #[test] fn test_safe_body1() { #[safe_body] unsafe fn some_func((x, mut y): (u32, u32)) -> u32 { let z: u32 = unsafe { std::mem::zeroed() }; y += z; x + y } assert_eq!(unsafe { some_func((4, 3)) }, 4 + 3); } #[test] fn raw_identifier() { #[unsafe_fn] fn r#unsafe(r#u32: u32) -> u32 { return r#u32; } assert_eq!(unsafe { r#unsafe(5) }, 5); } trait SomeTrait { #[unsafe_fn] fn foo(&self) -> u32; #[unsafe_fn] fn bar(&self) -> u32 { unsafe { self.foo() } } #[unsafe_fn] fn generic(&self) -> Q where Q: Default; } impl SomeTrait for u32 { #[unsafe_fn] fn foo(&self) -> u32 { let _: u32 = unsafe { std::mem::zeroed() }; *self } #[unsafe_fn] fn bar(&self) -> u32 { unsafe { self.foo() + 2 } } #[unsafe_fn] fn generic(&self) -> R where R: Default, { R::default() } }