Skip to content

Commit 68651a3

Browse files
Add Transitive casting and testing code
1 parent a662b2e commit 68651a3

File tree

11 files changed

+74
-29
lines changed

11 files changed

+74
-29
lines changed

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

+17-9
Original file line numberDiff line numberDiff line change
@@ -77,17 +77,25 @@ impl GeneratedRustFragment {
7777
unsafe fn #downcast_fn(base: *const #base_unqualified) -> *const #struct_name_unqualified;
7878
}
7979
}],
80-
cxx_qt_mod_contents: vec![parse_quote! {
81-
impl ::cxx_qt::Upcast<#base_qualified> for #struct_name {
82-
unsafe fn upcast_ptr(this: *const Self) -> *const #base_qualified {
83-
#upcast_fn_qualified(this)
84-
}
80+
cxx_qt_mod_contents: vec![
81+
parse_quote! {
82+
unsafe impl ::cxx_qt::Upcast<#base_qualified> for #struct_name {
83+
unsafe fn upcast_ptr(this: *const Self) -> *const #base_qualified {
84+
#upcast_fn_qualified(this)
85+
}
8586

86-
unsafe fn from_base_ptr(base: *const #base_qualified) -> *const Self {
87-
#downcast_fn_qualified(base)
87+
unsafe fn from_base_ptr(base: *const #base_qualified) -> *const Self {
88+
#downcast_fn_qualified(base)
89+
}
8890
}
89-
}
90-
}],
91+
},
92+
// Add back once we figure out the bug with QObject, for automatic transitive casts
93+
// parse_quote! {
94+
// unsafe impl ::cxx_qt::MainCast for #struct_name {
95+
// type Base = #base_qualified;
96+
// }
97+
// }
98+
],
9199
})
92100
}
93101

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

+4-4
Original file line numberDiff line numberDiff line change
@@ -668,7 +668,7 @@ cxx_qt::static_assertions::assert_eq_size!(
668668
cxx_qt::signalhandler::CxxQtSignalHandler<QObjectEnabledCxxQtSignalClosuresignal_enabled>,
669669
[usize; 2]
670670
);
671-
impl ::cxx_qt::Upcast<::cxx_qt::QObject> for ffi::QObjectEnabled {
671+
unsafe impl ::cxx_qt::Upcast<::cxx_qt::QObject> for ffi::QObjectEnabled {
672672
unsafe fn upcast_ptr(this: *const Self) -> *const ::cxx_qt::QObject {
673673
ffi::cxx_qt_ffi_QObjectEnabled_upcastPtr(this)
674674
}
@@ -847,7 +847,7 @@ cxx_qt::static_assertions::assert_eq_size!(
847847
cxx_qt::signalhandler::CxxQtSignalHandler<QObjectDisabledCxxQtSignalClosuresignal_enabled>,
848848
[usize; 2]
849849
);
850-
impl ::cxx_qt::Upcast<::cxx_qt::QObject> for ffi::QObjectDisabled {
850+
unsafe impl ::cxx_qt::Upcast<::cxx_qt::QObject> for ffi::QObjectDisabled {
851851
unsafe fn upcast_ptr(this: *const Self) -> *const ::cxx_qt::QObject {
852852
ffi::cxx_qt_ffi_QObjectDisabled_upcastPtr(this)
853853
}
@@ -878,7 +878,7 @@ impl ::cxx_qt::CxxQtType for ffi::QObjectDisabled {
878878
ffi::cxx_qt_ffi_QObjectDisabled_unsafeRustMut(self)
879879
}
880880
}
881-
impl ::cxx_qt::Upcast<::cxx_qt::QObject> for ffi::QObjectExternEnabled {
881+
unsafe impl ::cxx_qt::Upcast<::cxx_qt::QObject> for ffi::QObjectExternEnabled {
882882
unsafe fn upcast_ptr(this: *const Self) -> *const ::cxx_qt::QObject {
883883
ffi::cxx_qt_ffi_QObjectExternEnabled_upcastPtr(this)
884884
}
@@ -1048,7 +1048,7 @@ cxx_qt::static_assertions::assert_eq_size!(
10481048
>,
10491049
[usize; 2]
10501050
);
1051-
impl ::cxx_qt::Upcast<::cxx_qt::QObject> for ffi::QObjectExternDisabled {
1051+
unsafe impl ::cxx_qt::Upcast<::cxx_qt::QObject> for ffi::QObjectExternDisabled {
10521052
unsafe fn upcast_ptr(this: *const Self) -> *const ::cxx_qt::QObject {
10531053
ffi::cxx_qt_ffi_QObjectExternDisabled_upcastPtr(this)
10541054
}

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

+3-3
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ mod inheritance {
130130
type QObject = cxx_qt::QObject;
131131
}
132132
}
133-
impl ::cxx_qt::Upcast<inheritance::QAbstractItemModel> for inheritance::MyObject {
133+
unsafe impl ::cxx_qt::Upcast<inheritance::QAbstractItemModel> for inheritance::MyObject {
134134
unsafe fn upcast_ptr(this: *const Self) -> *const inheritance::QAbstractItemModel {
135135
inheritance::cxx_qt_ffi_MyObject_upcastPtr(this)
136136
}
@@ -158,15 +158,15 @@ impl ::cxx_qt::CxxQtType for inheritance::MyObject {
158158
inheritance::cxx_qt_ffi_MyObject_unsafeRustMut(self)
159159
}
160160
}
161-
impl ::cxx_qt::Upcast<::cxx_qt::QObject> for inheritance::QPushButton {
161+
unsafe impl ::cxx_qt::Upcast<::cxx_qt::QObject> for inheritance::QPushButton {
162162
unsafe fn upcast_ptr(this: *const Self) -> *const ::cxx_qt::QObject {
163163
inheritance::cxx_qt_ffi_QPushButton_upcastPtr(this)
164164
}
165165
unsafe fn from_base_ptr(base: *const ::cxx_qt::QObject) -> *const Self {
166166
inheritance::cxx_qt_ffi_QPushButton_downcastPtr(base)
167167
}
168168
}
169-
impl ::cxx_qt::Upcast<inheritance::QPushButton> for inheritance::QPushButtonChild {
169+
unsafe impl ::cxx_qt::Upcast<inheritance::QPushButton> for inheritance::QPushButtonChild {
170170
unsafe fn upcast_ptr(this: *const Self) -> *const inheritance::QPushButton {
171171
inheritance::cxx_qt_ffi_QPushButtonChild_upcastPtr(this)
172172
}

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@ impl cxx_qt::Threading for ffi::MyObject {
326326
pub struct MyObjectCxxQtThreadQueuedFn {
327327
inner: std::boxed::Box<dyn FnOnce(core::pin::Pin<&mut ffi::MyObject>) + Send>,
328328
}
329-
impl ::cxx_qt::Upcast<::cxx_qt::QObject> for ffi::MyObject {
329+
unsafe impl ::cxx_qt::Upcast<::cxx_qt::QObject> for ffi::MyObject {
330330
unsafe fn upcast_ptr(this: *const Self) -> *const ::cxx_qt::QObject {
331331
ffi::cxx_qt_ffi_MyObject_upcastPtr(this)
332332
}

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

+5-5
Original file line numberDiff line numberDiff line change
@@ -648,7 +648,7 @@ cxx_qt::static_assertions::assert_eq_size!(
648648
cxx_qt::signalhandler::CxxQtSignalHandler<MyObjectCxxQtSignalClosureready>,
649649
[usize; 2]
650650
);
651-
impl ::cxx_qt::Upcast<ffi::QStringListModel> for ffi::MyObject {
651+
unsafe impl ::cxx_qt::Upcast<ffi::QStringListModel> for ffi::MyObject {
652652
unsafe fn upcast_ptr(this: *const Self) -> *const ffi::QStringListModel {
653653
ffi::cxx_qt_ffi_MyObject_upcastPtr(this)
654654
}
@@ -822,7 +822,7 @@ cxx_qt::static_assertions::assert_eq_size!(
822822
cxx_qt::signalhandler::CxxQtSignalHandler<SecondObjectCxxQtSignalClosureready>,
823823
[usize; 2]
824824
);
825-
impl ::cxx_qt::Upcast<::cxx_qt::QObject> for ffi::SecondObject {
825+
unsafe impl ::cxx_qt::Upcast<::cxx_qt::QObject> for ffi::SecondObject {
826826
unsafe fn upcast_ptr(this: *const Self) -> *const ::cxx_qt::QObject {
827827
ffi::cxx_qt_ffi_SecondObject_upcastPtr(this)
828828
}
@@ -850,7 +850,7 @@ impl ::cxx_qt::CxxQtType for ffi::SecondObject {
850850
ffi::cxx_qt_ffi_SecondObject_unsafeRustMut(self)
851851
}
852852
}
853-
impl ::cxx_qt::Upcast<::cxx_qt::QObject> for ffi::MyRustName {
853+
unsafe impl ::cxx_qt::Upcast<::cxx_qt::QObject> for ffi::MyRustName {
854854
unsafe fn upcast_ptr(this: *const Self) -> *const ::cxx_qt::QObject {
855855
ffi::cxx_qt_ffi_MyCxxName_upcastPtr(this)
856856
}
@@ -878,15 +878,15 @@ impl ::cxx_qt::CxxQtType for ffi::MyRustName {
878878
ffi::cxx_qt_ffi_MyCxxName_unsafeRustMut(self)
879879
}
880880
}
881-
impl ::cxx_qt::Upcast<::cxx_qt::QObject> for ffi::QPushButton {
881+
unsafe impl ::cxx_qt::Upcast<::cxx_qt::QObject> for ffi::QPushButton {
882882
unsafe fn upcast_ptr(this: *const Self) -> *const ::cxx_qt::QObject {
883883
ffi::cxx_qt_ffi_QPushButton_upcastPtr(this)
884884
}
885885
unsafe fn from_base_ptr(base: *const ::cxx_qt::QObject) -> *const Self {
886886
ffi::cxx_qt_ffi_QPushButton_downcastPtr(base)
887887
}
888888
}
889-
impl ::cxx_qt::Upcast<::cxx_qt::QObject> for ffi::ExternObject {
889+
unsafe impl ::cxx_qt::Upcast<::cxx_qt::QObject> for ffi::ExternObject {
890890
unsafe fn upcast_ptr(this: *const Self) -> *const ::cxx_qt::QObject {
891891
ffi::cxx_qt_ffi_ExternObjectCpp_upcastPtr(this)
892892
}

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -1052,7 +1052,7 @@ cxx_qt::static_assertions::assert_eq_size!(
10521052
cxx_qt::signalhandler::CxxQtSignalHandler<MyObjectCxxQtSignalClosuremy_on_changed>,
10531053
[usize; 2]
10541054
);
1055-
impl ::cxx_qt::Upcast<::cxx_qt::QObject> for ffi::MyObject {
1055+
unsafe impl ::cxx_qt::Upcast<::cxx_qt::QObject> for ffi::MyObject {
10561056
unsafe fn upcast_ptr(this: *const Self) -> *const ::cxx_qt::QObject {
10571057
ffi::cxx_qt_ffi_MyObject_upcastPtr(this)
10581058
}

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ mod ffi {
169169
type QObject = cxx_qt::QObject;
170170
}
171171
}
172-
impl ::cxx_qt::Upcast<::cxx_qt::QObject> for ffi::MyObject {
172+
unsafe impl ::cxx_qt::Upcast<::cxx_qt::QObject> for ffi::MyObject {
173173
unsafe fn upcast_ptr(this: *const Self) -> *const ::cxx_qt::QObject {
174174
ffi::cxx_qt_ffi_MyObject_upcastPtr(this)
175175
}
@@ -197,7 +197,7 @@ impl ::cxx_qt::CxxQtType for ffi::MyObject {
197197
ffi::cxx_qt_ffi_MyObject_unsafeRustMut(self)
198198
}
199199
}
200-
impl ::cxx_qt::Upcast<::cxx_qt::QObject> for ffi::MyRenamedObject {
200+
unsafe impl ::cxx_qt::Upcast<::cxx_qt::QObject> for ffi::MyRenamedObject {
201201
unsafe fn upcast_ptr(this: *const Self) -> *const ::cxx_qt::QObject {
202202
ffi::cxx_qt_ffi_CxxName_upcastPtr(this)
203203
}

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,7 @@ cxx_qt::static_assertions::assert_eq_size!(
455455
cxx_qt::signalhandler::CxxQtSignalHandler<MyObjectCxxQtSignalClosurenewData>,
456456
[usize; 2]
457457
);
458-
impl ::cxx_qt::Upcast<::cxx_qt::QObject> for ffi::MyObject {
458+
unsafe impl ::cxx_qt::Upcast<::cxx_qt::QObject> for ffi::MyObject {
459459
unsafe fn upcast_ptr(this: *const Self) -> *const ::cxx_qt::QObject {
460460
ffi::cxx_qt_ffi_MyObject_upcastPtr(this)
461461
}
@@ -483,7 +483,7 @@ impl ::cxx_qt::CxxQtType for ffi::MyObject {
483483
ffi::cxx_qt_ffi_MyObject_unsafeRustMut(self)
484484
}
485485
}
486-
impl ::cxx_qt::Upcast<::cxx_qt::QObject> for ffi::QTimer {
486+
unsafe impl ::cxx_qt::Upcast<::cxx_qt::QObject> for ffi::QTimer {
487487
unsafe fn upcast_ptr(this: *const Self) -> *const ::cxx_qt::QObject {
488488
ffi::cxx_qt_ffi_QTimer_upcastPtr(this)
489489
}

crates/cxx-qt-lib/src/core/qstringlist.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ impl DerefMut for QStringList {
207207
}
208208
}
209209

210-
impl Upcast<QList_QString> for QStringList {
210+
unsafe impl Upcast<QList_QString> for QStringList {
211211
unsafe fn upcast_ptr(this: *const Self) -> *const QList_QString {
212212
ffi::upcast_qstringlist(this)
213213
}

crates/cxx-qt/src/lib.rs

+27-1
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ pub trait Threading: Sized {
130130
/// This trait is automatically implemented by CXX-Qt and you most likely do not need to manually implement it.
131131
/// Allows upcasting to either [QObject] or the provided base class of a type.
132132
/// Will not be implemented if no types inherit from [QObject] or have the `#[base = T]` attribute.
133-
pub trait Upcast<T> {
133+
pub unsafe trait Upcast<T> {
134134
#[doc(hidden)]
135135
/// # Safety
136136
///
@@ -178,6 +178,32 @@ pub trait Upcast<T> {
178178
}
179179
}
180180

181+
/// Docs
182+
pub unsafe trait MainCast: Upcast<Self::Base> {
183+
/// The first parent of the Type
184+
type Base;
185+
}
186+
187+
unsafe impl<T, A, B> Upcast<B> for T
188+
where
189+
T: MainCast<Base = A>,
190+
A: MainCast<Base = B>,
191+
{
192+
unsafe fn upcast_ptr(this: *const Self) -> *const B {
193+
let base = Self::upcast_ptr(this);
194+
A::upcast_ptr(base)
195+
}
196+
197+
unsafe fn from_base_ptr(base: *const B) -> *const Self {
198+
let base = A::from_base_ptr(base);
199+
if base.is_null() {
200+
std::ptr::null()
201+
} else {
202+
Self::from_base_ptr(base)
203+
}
204+
}
205+
}
206+
181207
/// This trait is automatically implemented by CXX-Qt and you most likely do not need to manually implement it.
182208
/// Trait for downcasting to a subclass, provided the subclass implements [Upcast] to this type.
183209
/// Returns `None` in cases where `Sub` isn't a child class of `Self`.

examples/qml_minimal/qml/main.qml

+11
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ ApplicationWindow {
2828
string: qsTr("My String with my number: %1").arg(myObject.number)
2929
}
3030

31+
A {
32+
id: a
33+
number: 10
34+
}
35+
3136
Column {
3237
anchors.fill: parent
3338
anchors.margins: 10
@@ -55,6 +60,12 @@ ApplicationWindow {
5560
onClicked: myObject.sayHi(myObject.string, myObject.number)
5661
}
5762

63+
Button {
64+
text: qsTr("Test A")
65+
66+
onClicked: a.test()
67+
}
68+
5869
Button {
5970
text: qsTr("Quit")
6071

0 commit comments

Comments
 (0)