Skip to content

Commit 98a7c92

Browse files
committed
Add lifetime to MatSize
1 parent f4d6321 commit 98a7c92

File tree

16 files changed

+149
-41
lines changed

16 files changed

+149
-41
lines changed

binding-generator/src/settings.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ pub use argument_override::{
4646
arg_override_factory, property_override_factory, return_override_factory, ArgOverride, PropertyOverride, ReturnOverride,
4747
ARG_OVERRIDE_SELF,
4848
};
49+
pub use class_tweak::{ClassTweak, CLASS_TWEAK};
4950
pub use const_tweak::CONST_TYPE_OVERRIDE;
5051
pub use element_exclude_kind::ELEMENT_EXCLUDE_KIND;
5152
pub use element_export_tweak::ELEMENT_EXPORT_TWEAK;
@@ -71,6 +72,7 @@ use crate::type_ref::TypeRef;
7172

7273
mod argument_names;
7374
mod argument_override;
75+
mod class_tweak;
7476
mod const_tweak;
7577
mod element_exclude_kind;
7678
mod element_export_tweak;
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
use std::collections::HashMap;
2+
3+
use once_cell::sync::Lazy;
4+
5+
use crate::writer::rust_native::type_ref::Lifetime;
6+
7+
#[derive(Clone, Copy)]
8+
pub enum ClassTweak {
9+
Lifetime(Lifetime),
10+
}
11+
12+
pub static CLASS_TWEAK: Lazy<HashMap<&str, ClassTweak>> =
13+
Lazy::new(|| HashMap::from([("cv::MatSize", ClassTweak::Lifetime(Lifetime::Custom("mat")))]));

binding-generator/src/type_ref/kind.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,28 @@ impl<'tu, 'ge> TypeRefKind<'tu, 'ge> {
456456
kind => kind.extern_pass_kind().is_by_void_ptr() || kind.as_string(type_hint).is_some(),
457457
}
458458
}
459+
460+
/// True if it's possible to borrow from this type in Rust
461+
///
462+
/// Used mainly to decide whether the return type of function should have explicit or elided lifetime.
463+
pub fn rust_can_borrow(&self, type_hint: &TypeRefTypeHint) -> bool {
464+
match self {
465+
TypeRefKind::Array(elem, _) => elem.kind().rust_can_borrow(type_hint),
466+
TypeRefKind::StdVector(vec) => vec.element_type().kind().rust_can_borrow(type_hint),
467+
TypeRefKind::StdTuple(tup) => tup.elements().iter().any(|e| e.kind().rust_can_borrow(type_hint)),
468+
TypeRefKind::RValueReference(inner) => inner.kind().rust_can_borrow(type_hint),
469+
TypeRefKind::SmartPtr(ptr) => ptr.pointee().kind().rust_can_borrow(type_hint),
470+
TypeRefKind::Typedef(tdef) => tdef.underlying_type_ref().kind().rust_can_borrow(type_hint),
471+
TypeRefKind::Pointer(_) if self.is_rust_by_ptr(type_hint) => false,
472+
TypeRefKind::Pointer(_) | TypeRefKind::Reference(_) => true,
473+
TypeRefKind::Primitive(_, _)
474+
| TypeRefKind::Class(_)
475+
| TypeRefKind::Enum(_)
476+
| TypeRefKind::Function(_)
477+
| TypeRefKind::Generic(_)
478+
| TypeRefKind::Ignored => false,
479+
}
480+
}
459481
}
460482

461483
#[derive(Clone, Copy, Debug)]

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

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ use std::borrow::Cow;
55
use super::element::{DefaultRustNativeElement, RustElement};
66
use super::RustNativeGeneratedElement;
77
use crate::class::ClassKind;
8+
use crate::settings::ClassTweak;
89
use crate::type_ref::{Constness, CppNameStyle, FishStyle, NameStyle};
9-
use crate::{Class, Element, Func, IteratorExt};
10+
use crate::writer::rust_native::type_ref::Lifetime;
11+
use crate::{settings, Class, Element, Func, IteratorExt};
1012

1113
impl RustElement for Class<'_, '_> {
1214
fn rust_module(&self) -> Cow<str> {
@@ -77,6 +79,8 @@ impl RustNativeGeneratedElement for Class<'_, '_> {
7779
pub trait ClassExt {
7880
fn rust_trait_name(&self, style: NameStyle, constness: Constness) -> Cow<str>;
7981
fn rust_as_raw_name(&self, constness: Constness) -> String;
82+
fn rust_lifetime(&self) -> Option<Lifetime>;
83+
fn rust_lifetime_count(&self) -> usize;
8084
}
8185

8286
impl ClassExt for Class<'_, '_> {
@@ -99,6 +103,19 @@ impl ClassExt for Class<'_, '_> {
99103
name = self.rust_name(NameStyle::Declaration)
100104
)
101105
}
106+
107+
fn rust_lifetime(&self) -> Option<Lifetime> {
108+
#[allow(clippy::bind_instead_of_map)]
109+
settings::CLASS_TWEAK
110+
.get(self.cpp_name(CppNameStyle::Reference).as_ref())
111+
.and_then(|tweak| match tweak {
112+
ClassTweak::Lifetime(lt) => Some(*lt),
113+
})
114+
}
115+
116+
fn rust_lifetime_count(&self) -> usize {
117+
self.rust_lifetime().map_or(0, |_| 1)
118+
}
102119
}
103120

104121
pub fn rust_generate_debug_fields<'f>(field_const_methods: impl IntoIterator<Item = Func<'f, 'f>>) -> String {

binding-generator/src/writer/rust_native/class/gen.rs

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,13 @@ pub fn gen_simple_class(c: &Class, opencv_version: &str) -> String {
6161
("fields", &fields),
6262
(
6363
"impl",
64-
&gen_impl(c, const_methods.iter().chain(mut_methods.iter()), &rust_local, opencv_version),
64+
&gen_impl(
65+
c,
66+
const_methods.iter().chain(mut_methods.iter()),
67+
&rust_local,
68+
"",
69+
opencv_version,
70+
),
6571
),
6672
("impls", &impls),
6773
]))
@@ -89,6 +95,15 @@ pub fn gen_boxed_class(c: &Class, opencv_version: &str) -> String {
8995
const_methods.extend(more_const_methods);
9096
mut_methods.extend(more_mut_methods);
9197

98+
let lt = c.rust_lifetime();
99+
let rust_decl_lt = lt.map_or_else(|| "".to_string(), |lt| format!("<{}>", lt.to_explicit()));
100+
let rust_decl_for_lt = lt.map_or_else(|| "".to_string(), |lt| format!(": for <{}>", lt.to_explicit()));
101+
let rust_elided_lt = lt.map_or_else(|| "".to_string(), |_| "<'_>".to_string());
102+
let rust_phantom_ref = lt.map_or_else(
103+
|| "".to_string(),
104+
|lt| format!("_d: PhantomData<&{} mut ()>,", lt.to_explicit()),
105+
);
106+
92107
let type_ref = c.type_ref();
93108
let bases = c.bases();
94109

@@ -128,7 +143,8 @@ pub fn gen_boxed_class(c: &Class, opencv_version: &str) -> String {
128143
"base_rust_full_const",
129144
&base.rust_trait_name(NameStyle::ref_(), Constness::Const),
130145
),
131-
("rust_local", &type_ref.rust_name(NameStyle::decl())),
146+
("rust_local", &rust_local),
147+
("rust_elided_lt", &rust_elided_lt),
132148
("rust_as_raw_const", &base.rust_as_raw_name(Constness::Const)),
133149
("rust_as_raw_mut", &base.rust_as_raw_name(Constness::Mut)),
134150
(
@@ -164,6 +180,10 @@ pub fn gen_boxed_class(c: &Class, opencv_version: &str) -> String {
164180
("doc_comment", c.rendered_doc_comment("///", opencv_version).as_str()),
165181
("debug", &c.get_debug()),
166182
("rust_local", &rust_local),
183+
("rust_decl_lt", &rust_decl_lt),
184+
("rust_decl_for_lt", &rust_decl_for_lt),
185+
("rust_elided_lt", &rust_elided_lt),
186+
("rust_phantom_ref", &rust_phantom_ref),
167187
("rust_full", &c.rust_name(NameStyle::ref_())),
168188
(
169189
"rust_extern_const",
@@ -179,7 +199,7 @@ pub fn gen_boxed_class(c: &Class, opencv_version: &str) -> String {
179199
("traits", &traits),
180200
("extern_delete", &extern_delete),
181201
("bases", &bases),
182-
("impl", &gen_impl(c, methods, &rust_local, opencv_version)),
202+
("impl", &gen_impl(c, methods, &rust_local, &rust_decl_lt, opencv_version)),
183203
("impls", &impls),
184204
]))
185205
}
@@ -296,7 +316,13 @@ fn all_methods_const_mut<'tu, 'ge>(c: &Class<'tu, 'ge>) -> (Vec<Func<'tu, 'ge>>,
296316
(const_methods, mut_methods)
297317
}
298318

299-
fn gen_impl<'f>(c: &Class, methods: impl Iterator<Item = &'f Func<'f, 'f>>, rust_local: &str, opencv_version: &str) -> String {
319+
fn gen_impl<'f>(
320+
c: &Class,
321+
methods: impl Iterator<Item = &'f Func<'f, 'f>>,
322+
rust_local: &str,
323+
rust_decl_lt: &str,
324+
opencv_version: &str,
325+
) -> String {
300326
static IMPL_TPL: Lazy<CompiledInterpolation> = Lazy::new(|| include_str!("../tpl/class/impl.tpl.rs").compile_interpolation());
301327

302328
let consts = c.consts().iter().map(|c| c.gen_rust(opencv_version)).join("");
@@ -310,6 +336,7 @@ fn gen_impl<'f>(c: &Class, methods: impl Iterator<Item = &'f Func<'f, 'f>>, rust
310336
} else {
311337
IMPL_TPL.interpolate(&HashMap::from([
312338
("rust_local", rust_local),
339+
("rust_decl_lt", rust_decl_lt),
313340
("consts", &consts),
314341
("inherent_methods", &inherent_methods),
315342
]))

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

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use crate::func::{FuncCppBody, FuncKind, FuncRustBody, FuncRustExtern, InheritCo
1515
use crate::name_pool::NamePool;
1616
use crate::settings::ARG_OVERRIDE_SELF;
1717
use crate::type_ref::{Constness, CppNameStyle, ExternDir, FishStyle, NameStyle, StrEnc, StrType, TypeRef, TypeRefTypeHint};
18+
use crate::writer::rust_native::class::ClassExt;
1819
use crate::writer::rust_native::type_ref::render_lane::FunctionProps;
1920
use crate::{reserved_rename, CompiledInterpolation, Element, Func, IteratorExt, NameDebug, StrExt, StringExt};
2021

@@ -221,6 +222,7 @@ impl RustNativeGeneratedElement for Func<'_, '_> {
221222
let mut forward_args = Vec::with_capacity(args.len());
222223
let mut post_success_call_args = Vec::with_capacity(args.len());
223224
let boxed_ref_arg = return_type_ref.type_hint().as_boxed_as_ref();
225+
let mut any_arg_can_borrow = false;
224226
if let Some(cls) = as_instance_method {
225227
let constness = self.constness();
226228
let cls_type_ref = cls.type_ref().with_inherent_constness(constness);
@@ -231,6 +233,7 @@ impl RustNativeGeneratedElement for Func<'_, '_> {
231233
.map_or(Lifetime::Elided, |(_, _, lt)| lt);
232234
decl_args.push(render_lane.rust_self_func_decl(lt));
233235
call_args.push(render_lane.rust_arg_func_call("self"));
236+
any_arg_can_borrow |= !cls_type_ref.kind().is_copy(cls_type_ref.type_hint());
234237
}
235238
let mut callback_arg_name: Option<&str> = None;
236239
let function_props = FunctionProps {
@@ -244,6 +247,7 @@ impl RustNativeGeneratedElement for Func<'_, '_> {
244247
let arg_kind = arg_type_ref.kind();
245248
let render_lane = arg_type_ref.render_lane();
246249
let render_lane = render_lane.to_dyn();
250+
any_arg_can_borrow |= arg_kind.rust_can_borrow(&arg_type_hint);
247251
if arg.is_user_data() {
248252
pre_post_arg_handle(
249253
format!(
@@ -312,8 +316,20 @@ impl RustNativeGeneratedElement for Func<'_, '_> {
312316
};
313317
let return_lifetime = match boxed_ref_arg {
314318
Some((_, _, lifetime)) => lifetime,
315-
None if matches!(kind.as_ref(), FuncKind::Function | FuncKind::StaticMethod(_)) => Lifetime::statik(),
316-
None => Lifetime::Elided,
319+
None => {
320+
if matches!(kind.as_ref(), FuncKind::Function | FuncKind::StaticMethod(_)) {
321+
Lifetime::statik()
322+
} else if let Some(lt) = return_type_ref
323+
.kind()
324+
.as_class()
325+
.and_then(|cls| cls.rust_lifetime())
326+
.filter(|_| !any_arg_can_borrow)
327+
{
328+
lt
329+
} else {
330+
Lifetime::Elided
331+
}
332+
}
317333
};
318334
let mut return_type_func_decl = return_type_ref.rust_return(FishStyle::No, return_lifetime);
319335
if !return_kind.is_infallible() {

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

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,18 @@ use crate::renderer::TypeRefRenderer;
55
use crate::type_ref::{
66
Constness, CppNameStyle, Dir, ExternDir, FishStyle, NameStyle, StrType, TemplateArg, TypeRef, TypeRefDesc, TypeRefKind,
77
};
8+
use crate::writer::rust_native::class::ClassExt;
89
use crate::writer::rust_native::element::RustElement;
910
use crate::writer::rust_native::function::FunctionExt;
1011
use crate::writer::rust_native::type_ref::{Lifetime, NullabilityExt, TypeRefExt};
1112
use crate::{settings, CowMapBorrowedExt, Element, IteratorExt};
1213

13-
fn render_rust_tpl<'a>(renderer: impl TypeRefRenderer<'a>, type_ref: &TypeRef, fish_style: FishStyle) -> String {
14+
fn render_rust_tpl<'a>(
15+
renderer: impl TypeRefRenderer<'a>,
16+
type_ref: &TypeRef,
17+
lifetime: Lifetime,
18+
fish_style: FishStyle,
19+
) -> String {
1420
let generic_types = type_ref.template_specialization_args();
1521
if !generic_types.is_empty() {
1622
let const_generics_implemented = type_ref
@@ -30,8 +36,13 @@ fn render_rust_tpl<'a>(renderer: impl TypeRefRenderer<'a>, type_ref: &TypeRef, f
3036
}
3137
TemplateArg::Unknown => None,
3238
});
33-
let generics = generic_types.join(", ");
39+
let mut generics = generic_types.join(", ");
40+
if lifetime.is_explicit() {
41+
generics.insert_str(0, &format!("{lifetime}, "));
42+
}
3443
format!("{constant_suffix}{fish}<{generics}>", fish = fish_style.rust_qual())
44+
} else if lifetime.is_explicit() {
45+
format!("{fish}<{lifetime}>", fish = fish_style.rust_qual())
3546
} else {
3647
"".to_string()
3748
}
@@ -109,10 +120,11 @@ impl TypeRefRenderer<'_> for RustRenderer {
109120
}
110121
TypeRefKind::Class(cls) => {
111122
let fish_style = self.name_style.turbo_fish_style();
123+
let lifetime = cls.rust_lifetime().map_or(Lifetime::Elided, |_| self.lifetime);
112124
format!(
113125
"{name}{generic}",
114126
name = cls.rust_name(self.name_style),
115-
generic = render_rust_tpl(self, type_ref, fish_style),
127+
generic = render_rust_tpl(self, type_ref, lifetime, fish_style),
116128
)
117129
.into()
118130
}
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
impl {{base_rust_full_const}} for {{rust_local}} {
1+
impl {{base_rust_full_const}} for {{rust_local}}{{rust_elided_lt}} {
22
#[inline] fn {{rust_as_raw_const}}(&self) -> {{base_rust_extern_const}} { self.as_raw() }
33
}
44

5-
impl {{base_rust_full_mut}} for {{rust_local}} {
5+
impl {{base_rust_full_mut}} for {{rust_local}}{{rust_elided_lt}} {
66
#[inline] fn {{rust_as_raw_mut}}(&mut self) -> {{base_rust_extern_mut}} { self.as_raw_mut() }
77
}
88

9-
boxed_ref! { {{rust_local}}, {{base_rust_full_const}}, {{rust_as_raw_const}}, {{base_rust_full_mut}}, {{rust_as_raw_mut}} }
9+
boxed_ref! { {{rust_local}}{{rust_elided_lt}}, {{base_rust_full_const}}, {{rust_as_raw_const}}, {{base_rust_full_mut}}, {{rust_as_raw_mut}} }
1010

1111

binding-generator/src/writer/rust_native/tpl/class/boxed.tpl.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
11
{{doc_comment}}
22
{{debug}}
3-
pub struct {{rust_local}} {
3+
pub struct {{rust_local}}{{rust_decl_lt}} {
44
ptr: {{rust_extern_mut}},
5+
{{rust_phantom_ref}}
56
}
67

7-
opencv_type_boxed! { {{rust_local}} }
8+
opencv_type_boxed! { {{rust_local}}{{rust_decl_lt}}{{rust_decl_for_lt}} }
89

9-
impl Drop for {{rust_local}} {
10+
impl Drop for {{rust_local}}{{rust_elided_lt}} {
1011
#[inline]
1112
fn drop(&mut self) {
1213
unsafe { sys::{{extern_delete}}(self.as_raw_mut_{{rust_local}}()) };
1314
}
1415
}
1516

16-
unsafe impl Send for {{rust_local}} {}
17+
unsafe impl Send for {{rust_local}}{{rust_elided_lt}} {}
1718

1819
{{impl}}
1920
{{traits}}

binding-generator/src/writer/rust_native/tpl/class/impl.tpl.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
impl {{rust_local}} {
1+
impl{{rust_decl_lt}} {{rust_local}}{{rust_decl_lt}} {
22
{{consts}}
33
{{inherent_methods}}
44
}

0 commit comments

Comments
 (0)