Skip to content

Commit 3a3ce84

Browse files
committed
Add lifetime to MatSize
1 parent 658ddd6 commit 3a3ce84

File tree

16 files changed

+183
-81
lines changed

16 files changed

+183
-81
lines changed

binding-generator/src/settings.rs

Lines changed: 5 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_tweaks::{class_tweaks_factory, ClassTweak, ClassTweaks};
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_tweaks;
7476
mod const_tweak;
7577
mod element_exclude_kind;
7678
mod element_export_tweak;
@@ -106,6 +108,7 @@ pub struct Settings {
106108
pub generator_module_tweaks: ModuleTweak<'static>,
107109
pub property_override: PropertyOverride,
108110
pub property_tweaks: PropertyTweaks,
111+
pub class_tweak: ClassTweaks,
109112
}
110113

111114
impl Settings {
@@ -125,6 +128,7 @@ impl Settings {
125128
generator_module_tweaks: ModuleTweak::empty(),
126129
property_override: PropertyOverride::default(),
127130
property_tweaks: PropertyTweaks::default(),
131+
class_tweak: ClassTweaks::default(),
128132
}
129133
}
130134

@@ -144,6 +148,7 @@ impl Settings {
144148
generator_module_tweaks: generator_module_tweaks_factory(module),
145149
property_override: property_override_factory(module),
146150
property_tweaks: property_tweaks_factory(module),
151+
class_tweak: class_tweaks_factory(module),
147152
}
148153
}
149154

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
use std::collections::HashMap;
2+
3+
use crate::writer::rust_native::type_ref::Lifetime;
4+
5+
pub type ClassTweaks = HashMap<&'static str, ClassTweak>;
6+
7+
#[derive(Clone, Copy, Debug)]
8+
pub enum ClassTweak {
9+
Lifetime(Lifetime),
10+
}
11+
12+
pub fn class_tweaks_factory(module: &str) -> ClassTweaks {
13+
match module {
14+
"core" => HashMap::from([("cv::MatSize", ClassTweak::Lifetime(Lifetime::Custom("mat")))]),
15+
_ => HashMap::default(),
16+
}
17+
}

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: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ 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};
10+
use crate::writer::rust_native::type_ref::Lifetime;
911
use crate::{Class, Element, Func, IteratorExt};
1012

1113
impl RustElement for Class<'_, '_> {
@@ -77,6 +79,7 @@ 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>;
8083
}
8184

8285
impl ClassExt for Class<'_, '_> {
@@ -99,6 +102,24 @@ impl ClassExt for Class<'_, '_> {
99102
name = self.rust_name(NameStyle::Declaration)
100103
)
101104
}
105+
106+
/// Rust lifetime use by the objects of this class
107+
fn rust_lifetime(&self) -> Option<Lifetime> {
108+
match self {
109+
Class::Clang { gen_env, .. } =>
110+
{
111+
#[allow(clippy::bind_instead_of_map)]
112+
gen_env
113+
.settings
114+
.class_tweak
115+
.get(self.cpp_name(CppNameStyle::Reference).as_ref())
116+
.and_then(|tweak| match tweak {
117+
ClassTweak::Lifetime(lt) => Some(*lt),
118+
})
119+
}
120+
Class::Desc(_) => None,
121+
}
122+
}
102123
}
103124

104125
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: 55 additions & 45 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,10 +95,22 @@ 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 (rust_decl_lt, rust_decl_for_lt, rust_elided_lt, rust_phantom_ref) = if let Some(lt) = c.rust_lifetime() {
99+
let lt = lt.to_explicit();
100+
(
101+
format!("<{lt}>"),
102+
format!(": for <{lt}>"),
103+
"<'_>".to_string(),
104+
format!("_d: PhantomData<&{lt} mut ()>,"),
105+
)
106+
} else {
107+
("".to_string(), "".to_string(), "".to_string(), "".to_string())
108+
};
109+
92110
let type_ref = c.type_ref();
93111
let bases = c.bases();
94112

95-
let traits = gen_traits(c, &type_ref, &bases, &const_methods, &mut_methods, opencv_version);
113+
let traits = gen_traits(c, type_ref.clone(), &bases, &const_methods, &mut_methods, opencv_version);
96114

97115
let rust_local = c.rust_name(NameStyle::decl());
98116

@@ -116,7 +134,7 @@ pub fn gen_boxed_class(c: &Class, opencv_version: &str) -> String {
116134

117135
let mut bases = String::with_capacity(all_bases.len() * (BASE_TPL_SRC.len() + 64));
118136
all_bases.iter().chain(iter::once(c)).for_each(|base| {
119-
let base_type_ref = base.type_ref();
137+
let (base_type_ref_const, base_type_ref_mut) = make_const_mut(base.type_ref());
120138
BASE_TPL.interpolate_into(
121139
&mut bases,
122140
&HashMap::from([
@@ -128,22 +146,12 @@ pub fn gen_boxed_class(c: &Class, opencv_version: &str) -> String {
128146
"base_rust_full_const",
129147
&base.rust_trait_name(NameStyle::ref_(), Constness::Const),
130148
),
131-
("rust_local", &type_ref.rust_name(NameStyle::decl())),
149+
("rust_local", &rust_local),
150+
("rust_elided_lt", &rust_elided_lt),
132151
("rust_as_raw_const", &base.rust_as_raw_name(Constness::Const)),
133152
("rust_as_raw_mut", &base.rust_as_raw_name(Constness::Mut)),
134-
(
135-
"base_rust_extern_const",
136-
&base_type_ref
137-
.clone()
138-
.with_inherent_constness(Constness::Const)
139-
.rust_extern(ExternDir::ToCpp),
140-
),
141-
(
142-
"base_rust_extern_mut",
143-
&base_type_ref
144-
.with_inherent_constness(Constness::Mut)
145-
.rust_extern(ExternDir::ToCpp),
146-
),
153+
("base_rust_extern_const", &base_type_ref_const.rust_extern(ExternDir::ToCpp)),
154+
("base_rust_extern_mut", &base_type_ref_mut.rust_extern(ExternDir::ToCpp)),
147155
]),
148156
)
149157
});
@@ -160,26 +168,22 @@ pub fn gen_boxed_class(c: &Class, opencv_version: &str) -> String {
160168
kind.as_static_method().is_some() || kind.as_constructor().is_some()
161169
});
162170

171+
let (type_ref_const, type_ref_mut) = make_const_mut(type_ref);
163172
BOXED_TPL.interpolate(&HashMap::from([
164173
("doc_comment", c.rendered_doc_comment("///", opencv_version).as_str()),
165174
("debug", &c.get_debug()),
166175
("rust_local", &rust_local),
176+
("rust_decl_lt", &rust_decl_lt),
177+
("rust_decl_for_lt", &rust_decl_for_lt),
178+
("rust_elided_lt", &rust_elided_lt),
179+
("rust_phantom_ref", &rust_phantom_ref),
167180
("rust_full", &c.rust_name(NameStyle::ref_())),
168-
(
169-
"rust_extern_const",
170-
&type_ref
171-
.clone()
172-
.with_inherent_constness(Constness::Const)
173-
.rust_extern(ExternDir::ToCpp),
174-
),
175-
(
176-
"rust_extern_mut",
177-
&type_ref.with_inherent_constness(Constness::Mut).rust_extern(ExternDir::ToCpp),
178-
),
181+
("rust_extern_const", &type_ref_const.rust_extern(ExternDir::ToCpp)),
182+
("rust_extern_mut", &type_ref_mut.rust_extern(ExternDir::ToCpp)),
179183
("traits", &traits),
180184
("extern_delete", &extern_delete),
181185
("bases", &bases),
182-
("impl", &gen_impl(c, methods, &rust_local, opencv_version)),
186+
("impl", &gen_impl(c, methods, &rust_local, &rust_decl_lt, opencv_version)),
183187
("impls", &impls),
184188
]))
185189
}
@@ -293,7 +297,13 @@ fn all_methods_const_mut<'tu, 'ge>(c: &Class<'tu, 'ge>) -> (Vec<Func<'tu, 'ge>>,
293297
(const_methods, mut_methods)
294298
}
295299

296-
fn gen_impl<'f>(c: &Class, methods: impl Iterator<Item = &'f Func<'f, 'f>>, rust_local: &str, opencv_version: &str) -> String {
300+
fn gen_impl<'f>(
301+
c: &Class,
302+
methods: impl Iterator<Item = &'f Func<'f, 'f>>,
303+
rust_local: &str,
304+
rust_decl_lt: &str,
305+
opencv_version: &str,
306+
) -> String {
297307
static IMPL_TPL: Lazy<CompiledInterpolation> = Lazy::new(|| include_str!("../tpl/class/impl.tpl.rs").compile_interpolation());
298308

299309
let consts = c.consts().iter().map(|c| c.gen_rust(opencv_version)).join("");
@@ -307,6 +317,7 @@ fn gen_impl<'f>(c: &Class, methods: impl Iterator<Item = &'f Func<'f, 'f>>, rust
307317
} else {
308318
IMPL_TPL.interpolate(&HashMap::from([
309319
("rust_local", rust_local),
320+
("rust_decl_lt", rust_decl_lt),
310321
("consts", &consts),
311322
("inherent_methods", &inherent_methods),
312323
]))
@@ -315,7 +326,7 @@ fn gen_impl<'f>(c: &Class, methods: impl Iterator<Item = &'f Func<'f, 'f>>, rust
315326

316327
fn gen_traits(
317328
c: &Class,
318-
type_ref: &TypeRef,
329+
type_ref: TypeRef,
319330
bases: &[Class],
320331
const_methods: &[Func],
321332
mut_methods: &[Func],
@@ -358,6 +369,7 @@ fn gen_traits(
358369
opencv_version,
359370
);
360371

372+
let (type_ref_const, type_ref_mut) = make_const_mut(type_ref);
361373
TRAIT_TPL.interpolate(&HashMap::from([
362374
("debug", c.get_debug().as_str()),
363375
("rust_trait_local_mut", &c.rust_trait_name(NameStyle::decl(), Constness::Mut)),
@@ -368,20 +380,8 @@ fn gen_traits(
368380
("rust_as_raw_const", &c.rust_as_raw_name(Constness::Const)),
369381
("rust_as_raw_mut", &c.rust_as_raw_name(Constness::Mut)),
370382
("rust_name_ref", &c.rust_name(NameStyle::ref_())),
371-
(
372-
"rust_extern_const",
373-
&type_ref
374-
.clone()
375-
.with_inherent_constness(Constness::Const)
376-
.rust_extern(ExternDir::ToCpp),
377-
),
378-
(
379-
"rust_extern_mut",
380-
&type_ref
381-
.clone()
382-
.with_inherent_constness(Constness::Mut)
383-
.rust_extern(ExternDir::ToCpp),
384-
),
383+
("rust_extern_const", &type_ref_const.rust_extern(ExternDir::ToCpp)),
384+
("rust_extern_mut", &type_ref_mut.rust_extern(ExternDir::ToCpp)),
385385
("trait_bases_const", &trait_bases_const),
386386
("trait_bases_mut", &trait_bases_mut),
387387
("trait_const_methods", &trait_const_methods),
@@ -486,6 +486,16 @@ impl Impls for String {
486486
}
487487
}
488488

489+
fn make_const_mut<'tu, 'ge>(type_ref: TypeRef<'tu, 'ge>) -> (TypeRef<'tu, 'ge>, TypeRef<'tu, 'ge>) {
490+
if type_ref.inherent_constness().is_const() {
491+
let type_ref_mut = type_ref.clone().with_inherent_constness(Constness::Mut);
492+
(type_ref, type_ref_mut)
493+
} else {
494+
let type_ref_const = type_ref.clone().with_inherent_constness(Constness::Const);
495+
(type_ref_const, type_ref)
496+
}
497+
}
498+
489499
mod method {
490500
use crate::func::{FuncCppBody, FuncDesc, FuncKind, ReturnKind};
491501
use crate::type_ref::TypeRef;

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

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use crate::func::{FuncCppBody, FuncKind, FuncRustBody, FuncRustExtern, InheritCo
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};
21+
use crate::writer::rust_native::class::ClassExt;
2122
use crate::writer::rust_native::type_ref::render_lane::FunctionProps;
2223
use crate::{reserved_rename, CompiledInterpolation, Element, Func, IteratorExt, NameDebug, StrExt, StringExt};
2324

@@ -232,6 +233,7 @@ impl RustNativeGeneratedElement for Func<'_, '_> {
232233
let mut forward_args = Vec::with_capacity(args.len());
233234
let mut post_success_call_args = Vec::with_capacity(args.len());
234235
let boxed_ref_arg = return_type_ref.type_hint().as_boxed_as_ref();
236+
let mut any_arg_can_borrow = false;
235237
if let Some(cls) = as_instance_method {
236238
let constness = self.constness();
237239
let cls_type_ref = cls.type_ref().with_inherent_constness(constness);
@@ -242,6 +244,7 @@ impl RustNativeGeneratedElement for Func<'_, '_> {
242244
.map_or(Lifetime::Elided, |(_, _, lt)| lt);
243245
decl_args.push(render_lane.rust_self_func_decl(lt));
244246
call_args.push(render_lane.rust_arg_func_call("self"));
247+
any_arg_can_borrow |= !cls_type_ref.kind().is_copy(cls_type_ref.type_hint());
245248
}
246249
let mut callback_arg_name: Option<&str> = None;
247250
let function_props = FunctionProps {
@@ -254,6 +257,7 @@ impl RustNativeGeneratedElement for Func<'_, '_> {
254257
let arg_kind = arg_type_ref.kind();
255258
let render_lane = arg_type_ref.render_lane();
256259
let render_lane = render_lane.to_dyn();
260+
any_arg_can_borrow |= arg_kind.rust_can_borrow(arg_type_hint);
257261
if arg.is_user_data() {
258262
pre_post_arg_handle(
259263
format!(
@@ -322,8 +326,20 @@ impl RustNativeGeneratedElement for Func<'_, '_> {
322326
};
323327
let return_lifetime = match boxed_ref_arg {
324328
Some((_, _, lifetime)) => lifetime,
325-
None if matches!(kind.as_ref(), FuncKind::Function | FuncKind::StaticMethod(_)) => Lifetime::statik(),
326-
None => Lifetime::Elided,
329+
None => {
330+
if matches!(kind.as_ref(), FuncKind::Function | FuncKind::StaticMethod(_)) {
331+
Lifetime::statik()
332+
} else if let Some(lt) = return_type_ref
333+
.kind()
334+
.as_class()
335+
.and_then(|cls| cls.rust_lifetime())
336+
.filter(|_| !any_arg_can_borrow)
337+
{
338+
lt
339+
} else {
340+
Lifetime::Elided
341+
}
342+
}
327343
};
328344
let mut return_type_func_decl = return_type_ref.rust_return(FishStyle::No, return_lifetime);
329345
if !return_kind.is_infallible() {

0 commit comments

Comments
 (0)