Skip to content

Commit a9f26a3

Browse files
Check constructor declarations
- A shim trait is used to check whether the user declared a constructor - This is implemented by the bridge if you add the constructor trait in bridge - This will then allow you to implemented constructor for your type - This prevents constructors not being used silently
1 parent 96d3233 commit a9f26a3

File tree

5 files changed

+29
-10
lines changed

5 files changed

+29
-10
lines changed

book/src/bridge/extern_rustqt.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ is equivalent to writing
111111
impl cxx_qt::Constructor<()> for x {}
112112
```
113113

114-
inside the bridge.
114+
inside the bridge. You can then implement your constructors outside the bridge, using either of these traits.
115115

116116
For further documentation see the [traits page](./traits.md).
117117

book/src/bridge/traits.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ For further documentation, refer to the documentation of the individual traits:
2323

2424
- [CxxQtType](https://docs.rs/cxx-qt/latest/cxx_qt/trait.CxxQtType.html) - trait to reach the Rust implementation of a `QObject`
2525
- This trait is automatically implemented for any `#[qobject]` type inside `extern "RustQt"` blocks.
26-
- [Constructor](https://docs.rs/cxx-qt/latest/cxx_qt/trait.Constructor.html) - custom constructor
26+
- [Constructor](https://docs.rs/cxx-qt/latest/cxx_qt/trait.Constructor.html) - custom constructor. This must be declared in the bridge in order for you to implement it outside the bridge
2727
- [Initialize](https://docs.rs/cxx-qt/latest/cxx_qt/trait.Initialize.html) - execute Rust code when the object is constructed, or as shorthand for an empty constructor
2828
- [Threading](https://docs.rs/cxx-qt/latest/cxx_qt/trait.Threading.html) - marker trait whether CXX-Qt threading should be enabled
2929

crates/cxx-qt-gen/src/generator/rust/constructor.rs

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,13 @@ pub fn generate(
207207

208208
let rust_struct_name_rust = qobject_names.rust_struct.rust_unqualified();
209209

210+
result
211+
.cxx_qt_mod_contents
212+
.append(&mut vec![parse_quote_spanned! {
213+
qobject_name_rust.span() => // TODO! Improve this span
214+
impl ::cxx_qt::ConstructorDeclared for #qobject_name_rust_qualified {}
215+
}]);
216+
210217
for (index, constructor) in constructors.iter().enumerate() {
211218
let lifetime = constructor.lifetime.as_ref().map(|lifetime| {
212219
quote! {
@@ -599,8 +606,16 @@ mod tests {
599606
},
600607
);
601608

609+
// Shim impl only appears once
602610
assert_tokens_eq(
603611
&blocks.cxx_qt_mod_contents[0],
612+
quote! {
613+
impl ::cxx_qt::ConstructorDeclared for qobject::MyObject {}
614+
},
615+
);
616+
617+
assert_tokens_eq(
618+
&blocks.cxx_qt_mod_contents[1],
604619
quote! {
605620
#[doc(hidden)]
606621
pub fn route_arguments_MyObject_0() -> qobject::CxxQtConstructorArgumentsMyObject0
@@ -619,7 +634,7 @@ mod tests {
619634
},
620635
);
621636
assert_tokens_eq(
622-
&blocks.cxx_qt_mod_contents[1],
637+
&blocks.cxx_qt_mod_contents[2],
623638
quote! {
624639
#[doc(hidden)]
625640
#[allow(unused_variables)]
@@ -633,7 +648,7 @@ mod tests {
633648
},
634649
);
635650
assert_tokens_eq(
636-
&blocks.cxx_qt_mod_contents[2],
651+
&blocks.cxx_qt_mod_contents[3],
637652
quote! {
638653
#[doc(hidden)]
639654
#[allow(unused_variables)]
@@ -725,7 +740,7 @@ mod tests {
725740
);
726741

727742
assert_tokens_eq(
728-
&blocks.cxx_qt_mod_contents[3],
743+
&blocks.cxx_qt_mod_contents[4],
729744
quote! {
730745
#[doc(hidden)]
731746
pub fn route_arguments_MyObject_1<'lifetime>(arg0: *const QObject) -> qobject::CxxQtConstructorArgumentsMyObject1<'lifetime>
@@ -753,7 +768,7 @@ mod tests {
753768
},
754769
);
755770
assert_tokens_eq(
756-
&blocks.cxx_qt_mod_contents[4],
771+
&blocks.cxx_qt_mod_contents[5],
757772
quote! {
758773
#[doc(hidden)]
759774
#[allow(unused_variables)]
@@ -767,7 +782,7 @@ mod tests {
767782
},
768783
);
769784
assert_tokens_eq(
770-
&blocks.cxx_qt_mod_contents[5],
785+
&blocks.cxx_qt_mod_contents[6],
771786
quote! {
772787
#[doc(hidden)]
773788
#[allow(unused_variables)]
@@ -806,7 +821,7 @@ mod tests {
806821
]);
807822

808823
assert_eq!(blocks.cxx_mod_contents.len(), 10);
809-
assert_eq!(blocks.cxx_qt_mod_contents.len(), 6);
824+
assert_eq!(blocks.cxx_qt_mod_contents.len(), 7);
810825

811826
let namespace_attr = quote! {
812827
#[namespace = "qobject::cxx_qt_MyObject"]

crates/cxx-qt-gen/test_outputs/invokables.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,7 @@ unsafe impl ::cxx_qt::casting::Upcast<::cxx_qt::QObject> for ffi::MyObject {
334334
ffi::cxx_qt_ffi_MyObject_downcastPtr(base)
335335
}
336336
}
337+
impl ::cxx_qt::ConstructorDeclared for ffi::MyObject {}
337338
#[doc(hidden)]
338339
pub fn route_arguments_MyObject_0<'a>(
339340
arg0: i32,

crates/cxx-qt/src/lib.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,9 @@ pub trait Threading: Sized {
216216
fn threading_drop(cxx_qt_thread: &mut CxxQtThread<Self>);
217217
}
218218

219+
#[doc(hidden)]
220+
pub trait ConstructorDeclared {}
221+
219222
/// This trait can be implemented on any [CxxQtType] to define a
220223
/// custom constructor in C++ for the QObject.
221224
///
@@ -307,7 +310,7 @@ pub trait Threading: Sized {
307310
///
308311
/// If a QObject implements the `Initialize` trait, and the inner Rust struct is [Default]-constructible it will automatically implement `cxx_qt::Constructor<()>`.
309312
/// Additionally, implementing `impl cxx_qt::Initialize` will act as shorthand for `cxx_qt::Constructor<()>`.
310-
pub trait Constructor<Arguments>: CxxQtType {
313+
pub trait Constructor<Arguments>: CxxQtType + ConstructorDeclared {
311314
/// The arguments that are passed to the [`new()`](Self::new) function to construct the inner Rust struct.
312315
/// This must be a tuple of CXX compatible types.
313316
///
@@ -401,7 +404,7 @@ pub trait Initialize: CxxQtType {
401404

402405
impl<T> Constructor<()> for T
403406
where
404-
T: Initialize,
407+
T: Initialize + ConstructorDeclared,
405408
T::Rust: Default,
406409
{
407410
type NewArguments = ();

0 commit comments

Comments
 (0)