Skip to content

Commit 4cabf1b

Browse files
committed
Introduce unsafe_op_in_unsafe_fn lint
1 parent b2baa35 commit 4cabf1b

File tree

21 files changed

+88
-129
lines changed

21 files changed

+88
-129
lines changed

binding-generator/src/func.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -816,14 +816,6 @@ impl Safety {
816816
}
817817
}
818818

819-
/// Returns `""` or `"unsafe "`, for usage for unsafe blocks within functions with `self` safety
820-
pub fn rust_block_safety_qual(self) -> &'static str {
821-
match self {
822-
Safety::Safe => "unsafe ",
823-
Safety::Unsafe => "",
824-
}
825-
}
826-
827819
/// Returns `""` or `"unsafe "`, for usage as function declaration specifier
828820
pub fn rust_func_safety_qual(self) -> &'static str {
829821
match self {

binding-generator/src/writer/rust_native/func.rs

Lines changed: 9 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use super::element::{DefaultRustNativeElement, RustElement};
1414
use super::type_ref::{Lifetime, TypeRefExt};
1515
use super::{comment, rust_disambiguate_names, RustNativeGeneratedElement};
1616
use crate::field::Field;
17-
use crate::func::{FuncCppBody, FuncKind, FuncRustBody, FuncRustExtern, InheritConfig, OperatorKind, ReturnKind, Safety};
17+
use crate::func::{FuncCppBody, FuncKind, FuncRustBody, FuncRustExtern, InheritConfig, OperatorKind, ReturnKind};
1818
use crate::name_pool::NamePool;
1919
use crate::settings::ARG_OVERRIDE_SELF;
2020
use crate::type_ref::{Constness, CppNameStyle, ExternDir, FishStyle, NameStyle, StrEnc, StrType, TypeRef, TypeRefTypeHint};
@@ -246,7 +246,6 @@ impl RustNativeGeneratedElement for Func<'_, '_> {
246246
let mut callback_arg_name: Option<&str> = None;
247247
let function_props = FunctionProps {
248248
is_infallible: return_kind.is_infallible(),
249-
safety,
250249
};
251250
for (name, arg) in &args {
252251
let arg_type_ref = arg.type_ref();
@@ -335,7 +334,7 @@ impl RustNativeGeneratedElement for Func<'_, '_> {
335334
} else {
336335
format!(" -> {return_type_func_decl}")
337336
};
338-
let (ret_pre_call, ret_handle, ret_stmt) = rust_return(self, &return_type_ref, return_kind, safety, return_lifetime);
337+
let (ret_pre_call, ret_handle, ret_stmt) = rust_return(self, &return_type_ref, return_kind, return_lifetime);
339338
let mut attributes = Vec::with_capacity(2);
340339
if self.is_no_discard() {
341340
attributes.push(Borrowed("#[must_use]"));
@@ -360,7 +359,7 @@ impl RustNativeGeneratedElement for Func<'_, '_> {
360359
("return_pre_call", ret_pre_call),
361360
(
362361
"call",
363-
&rust_call(self, safety, &identifier, &name, &call_args, &forward_args, return_kind),
362+
&rust_call(self, &identifier, &name, &call_args, &forward_args, return_kind),
364363
),
365364
("return_handle", &ret_handle),
366365
("post_success_call_args", &post_success_call_args.join("\n")),
@@ -534,7 +533,6 @@ fn pre_post_arg_handle(mut arg: String, args: &mut Vec<String>) {
534533

535534
fn rust_call(
536535
f: &Func,
537-
func_safety: Safety,
538536
identifier: &str,
539537
func_name: &str,
540538
call_args: &[String],
@@ -543,7 +541,7 @@ fn rust_call(
543541
) -> String {
544542
#![allow(clippy::too_many_arguments)]
545543
static CALL_TPL: Lazy<CompiledInterpolation> =
546-
Lazy::new(|| "{{ret_receive}}{{unsafety_call}}{ sys::{{identifier}}({{call_args}}) };".compile_interpolation());
544+
Lazy::new(|| "{{ret_receive}}unsafe { sys::{{identifier}}({{call_args}}) };".compile_interpolation());
547545

548546
let ret_receive = if return_kind.is_naked() {
549547
"let ret = "
@@ -556,7 +554,6 @@ fn rust_call(
556554
};
557555
tpl.interpolate(&HashMap::from([
558556
("ret_receive", ret_receive),
559-
("unsafety_call", func_safety.rust_block_safety_qual()),
560557
("identifier", identifier),
561558
("name", func_name),
562559
("call_args", &call_args.join(", ")),
@@ -568,7 +565,6 @@ fn rust_return(
568565
f: &Func,
569566
return_type_ref: &TypeRef,
570567
return_kind: ReturnKind,
571-
safety: Safety,
572568
lifetime: Lifetime,
573569
) -> (&'static str, String, &'static str) {
574570
match f.rust_body() {
@@ -581,15 +577,12 @@ fn rust_return(
581577

582578
let mut ret_convert = Vec::with_capacity(3);
583579
if !return_kind.is_naked() {
584-
ret_convert.push(Owned(format!(
585-
"return_receive!({safety}ocvrs_return => ret);",
586-
safety = safety.rust_block_safety_qual()
587-
)));
580+
ret_convert.push(Borrowed("return_receive!(ocvrs_return => ret);"));
588581
}
589582
if !return_kind.is_infallible() {
590583
ret_convert.push("let ret = ret.into_result()?;".into())
591584
}
592-
let ret_map = rust_return_map(return_type_ref, "ret", safety, return_kind, lifetime);
585+
let ret_map = rust_return_map(return_type_ref, "ret", return_kind, lifetime);
593586
if !ret_map.is_empty() {
594587
ret_convert.push(format!("let ret = {ret_map};").into());
595588
}
@@ -605,18 +598,11 @@ fn rust_return(
605598
}
606599
}
607600

608-
fn rust_return_map(
609-
return_type: &TypeRef,
610-
ret_name: &str,
611-
context_safety: Safety,
612-
return_kind: ReturnKind,
613-
lifetime: Lifetime,
614-
) -> Cow<'static, str> {
615-
let unsafety_call = context_safety.rust_block_safety_qual();
601+
fn rust_return_map(return_type: &TypeRef, ret_name: &str, return_kind: ReturnKind, lifetime: Lifetime) -> Cow<'static, str> {
616602
let return_type_kind = return_type.kind();
617603
if return_type_kind.as_string(return_type.type_hint()).is_some() || return_type_kind.extern_pass_kind().is_by_void_ptr() {
618604
format!(
619-
"{unsafety_call}{{ {typ}::opencv_from_extern({ret_name}) }}",
605+
"unsafe {{ {typ}::opencv_from_extern({ret_name}) }}",
620606
typ = return_type.rust_return(FishStyle::Turbo, lifetime),
621607
)
622608
.into()
@@ -634,7 +620,7 @@ fn rust_return_map(
634620
} else {
635621
".ok_or_else(|| Error::new(core::StsNullPtr, \"Function returned null pointer\"))?"
636622
};
637-
format!("{unsafety_call}{{ {ret_name}.{ptr_call}() }}{error_handling}").into()
623+
format!("unsafe {{ {ret_name}.{ptr_call}() }}{error_handling}").into()
638624
} else {
639625
"".into()
640626
}

binding-generator/src/writer/rust_native/type_ref/render_lane.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ pub use string::{InStringRenderLane, OutStringRenderLane};
1414
pub use trait_class::TraitClassRenderLane;
1515
pub use void_slice::VoidSliceRenderLane;
1616

17-
use crate::func::Safety;
1817
use crate::type_ref::{Constness, TypeRef};
1918
use crate::writer::rust_native::type_ref::{Lifetime, TypeRefExt};
2019

@@ -146,7 +145,6 @@ fn rust_self_func_decl(method_constness: Constness, lifetime: Lifetime) -> Cow<'
146145

147146
pub struct FunctionProps {
148147
pub is_infallible: bool,
149-
pub safety: Safety,
150148
}
151149

152150
fn rust_arg_func_decl(name: &str, argument_constness: Constness, typ: &str) -> String {

binding-generator/src/writer/rust_native/type_ref/render_lane/cpp_pass_by_void_ptr.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,17 +37,14 @@ impl RenderLaneTrait for CppPassByVoidPtrRenderLane<'_, '_> {
3737
)
3838
}
3939

40-
fn rust_arg_pre_call(&self, name: &str, function_props: &FunctionProps) -> String {
40+
fn rust_arg_pre_call(&self, name: &str, _function_props: &FunctionProps) -> String {
4141
let is_nullable = self.non_canonical.type_hint().nullability().is_nullable();
4242
if is_nullable && self.non_canonical.source().kind().as_smart_ptr().is_some() {
4343
let ref_spec = match self.indirection {
4444
Indirection::Pointer | Indirection::Reference => "ref ",
4545
Indirection::None => "",
4646
};
47-
format!(
48-
"smart_ptr_option_arg!({safety}{ref_spec}{name})",
49-
safety = function_props.safety.rust_block_safety_qual()
50-
)
47+
format!("smart_ptr_option_arg!({ref_spec}{name})")
5148
} else {
5249
"".to_string()
5350
}

binding-generator/tests/generation.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ fn extract_functions(code: &str, cb: impl FnMut(Func)) {
7272
#[test]
7373
fn char_ptr_slice() {
7474
extract_functions("CV_EXPORTS int startLoop(int argc, char* argv[]);", |f| {
75-
assert_eq!(f.gen_rust("0.0.0").trim(), "#[inline]\npub fn start_loop(argv: &mut [&str]) -> Result<i32> {\n\tstring_array_arg_mut!(argv);\n\treturn_send!(via ocvrs_return);\n\tunsafe { sys::cv_startLoop_int_charXX(argv.len().try_into()?, argv.as_mut_ptr(), ocvrs_return.as_mut_ptr()) };\n\treturn_receive!(unsafe ocvrs_return => ret);\n\tlet ret = ret.into_result()?;\n\tOk(ret)\n}");
75+
assert_eq!(f.gen_rust("0.0.0").trim(), "#[inline]\npub fn start_loop(argv: &mut [&str]) -> Result<i32> {\n\tstring_array_arg_mut!(argv);\n\treturn_send!(via ocvrs_return);\n\tunsafe { sys::cv_startLoop_int_charXX(argv.len().try_into()?, argv.as_mut_ptr(), ocvrs_return.as_mut_ptr()) };\n\treturn_receive!(ocvrs_return => ret);\n\tlet ret = ret.into_result()?;\n\tOk(ret)\n}");
7676
assert_eq!(f.gen_cpp().trim(), "void cv_startLoop_int_charXX(int argc, char** argv, Result<int>* ocvrs_return) {\n\ttry {\n\t\tint ret = cv::startLoop(argc, argv);\n\t\tOk(ret, ocvrs_return);\n\t} OCVRS_CATCH(ocvrs_return);\n}");
7777
assert_eq!(
7878
f.gen_rust_externs().trim(),

build/generator/collector.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -193,13 +193,13 @@ impl<'r> Collector<'r> {
193193
// MSRV: use #[unsafe(no_mangle)] when MSRV is 1.82
194194
writeln!(
195195
hub_rs,
196-
r#"#[no_mangle] unsafe extern "C" fn ocvrs_create_string{}(s: *const c_char) -> *mut String {{ crate::templ::ocvrs_create_string(s) }}"#,
196+
r#"#[no_mangle] unsafe extern "C" fn ocvrs_create_string{}(s: *const c_char) -> *mut String {{ unsafe {{ crate::templ::ocvrs_create_string(s) }} }}"#,
197197
self.ffi_export_suffix
198198
)?;
199199
write!(hub_rs, "\t")?;
200200
writeln!(
201201
hub_rs,
202-
r#"#[no_mangle] unsafe extern "C" fn ocvrs_create_byte_string{}(v: *const u8, len: size_t) -> *mut Vec<u8> {{ crate::templ::ocvrs_create_byte_string(v, len) }}"#,
202+
r#"#[no_mangle] unsafe extern "C" fn ocvrs_create_byte_string{}(v: *const u8, len: size_t) -> *mut Vec<u8> {{ unsafe {{ crate::templ::ocvrs_create_byte_string(v, len) }} }}"#,
203203
self.ffi_export_suffix
204204
)?;
205205
writeln!(hub_rs, "}}")?;

src/boxed_ref.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ impl<T: OpenCVFromExtern + Boxed> OpenCVFromExtern for BoxedRef<'_, T> {
6060
#[inline]
6161
unsafe fn opencv_from_extern(s: Self::ExternReceive) -> Self {
6262
Self {
63-
reference: T::opencv_from_extern(s),
63+
reference: unsafe { T::opencv_from_extern(s) },
6464
referenced_object: PhantomData,
6565
}
6666
}
@@ -139,7 +139,7 @@ impl<T: OpenCVFromExtern + Boxed> OpenCVFromExtern for BoxedRefMut<'_, T> {
139139
#[inline]
140140
unsafe fn opencv_from_extern(s: Self::ExternReceive) -> Self {
141141
Self {
142-
reference: T::opencv_from_extern(s),
142+
reference: unsafe { T::opencv_from_extern(s) },
143143
referenced_object: PhantomData,
144144
}
145145
}

src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
#![allow(rustdoc::broken_intra_doc_links)]
2+
// MSRV: remove this hint when edition is "2024" because it's included in it
3+
#![deny(unsafe_op_in_unsafe_fn)]
24
//! Rust bindings for the OpenCV computer vision library
35
//!
46
//! [Git](https://github.com/twistedfall/opencv-rust) | [Readme](https://github.com/twistedfall/opencv-rust/blob/master/README.md) |

src/manual/core/inplace.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ pub trait ModifyInplace {
1616
impl<Mat: Boxed> ModifyInplace for Mat {
1717
#[inline(always)]
1818
unsafe fn modify_inplace<Res>(&mut self, f: impl FnOnce(&Self, &mut Self) -> Res) -> Res {
19-
let mut m_alias = Mat::from_raw(self.as_raw_mut());
19+
let mut m_alias = unsafe { Mat::from_raw(self.as_raw_mut()) };
2020
let out = f(self, &mut m_alias);
2121
// prevent running destructor on m_alias
2222
let _ = m_alias.into_raw();
@@ -27,7 +27,7 @@ impl<Mat: Boxed> ModifyInplace for Mat {
2727
impl<Mat: Boxed> ModifyInplace for BoxedRefMut<'_, Mat> {
2828
#[inline(always)]
2929
unsafe fn modify_inplace<Res>(&mut self, f: impl FnOnce(&Self, &mut Self) -> Res) -> Res {
30-
let mut m_alias = BoxedRefMut::from(Mat::from_raw(self.reference.as_raw_mut()));
30+
let mut m_alias = BoxedRefMut::from(unsafe { Mat::from_raw(self.reference.as_raw_mut()) });
3131
let out = f(self, &mut m_alias);
3232
// prevent running destructor on m_alias
3333
let _ = m_alias.reference.into_raw();

src/manual/core/input_output_array.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ fn call_input_array(input_array: &impl _InputArrayTraitConst) -> Result<BoxedRef
4545
}
4646
return_send!(via ocvrs_return);
4747
unsafe { cv_InputArray_input_array(input_array.as_raw__InputArray(), ocvrs_return.as_mut_ptr()) }
48-
return_receive!(unsafe ocvrs_return => ret);
48+
return_receive!(ocvrs_return => ret);
4949
ret.into_result().map(|ptr| unsafe { _InputArray::from_raw(ptr) }.into())
5050
}
5151

@@ -56,7 +56,7 @@ fn call_output_array(output_array: &mut impl _OutputArrayTrait) -> Result<BoxedR
5656
}
5757
return_send!(via ocvrs_return);
5858
unsafe { cv_OutputArray_output_array(output_array.as_raw_mut__OutputArray(), ocvrs_return.as_mut_ptr()) }
59-
return_receive!(unsafe ocvrs_return => ret);
59+
return_receive!(ocvrs_return => ret);
6060
ret.into_result().map(|ptr| unsafe { _OutputArray::from_raw(ptr) }.into())
6161
}
6262

@@ -103,7 +103,7 @@ impl ToInputOutputArray for _InputOutputArray {
103103
}
104104
return_send!(via ocvrs_return);
105105
unsafe { cv_InputOutputArray_input_output_array(self.as_raw_mut__InputOutputArray(), ocvrs_return.as_mut_ptr()) }
106-
return_receive!(unsafe ocvrs_return => ret);
106+
return_receive!(ocvrs_return => ret);
107107
ret.into_result()
108108
.map(|ptr| unsafe { _InputOutputArray::from_raw(ptr) }.into())
109109
}

0 commit comments

Comments
 (0)