Skip to content

Commit

Permalink
Merge pull request #1518 from felinira/wip/example-impl-trait-bounds
Browse files Browse the repository at this point in the history
examples: Add stricter impl trait bounds
  • Loading branch information
sdroege authored Sep 30, 2024
2 parents 1534916 + 983a59c commit 12d1877
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 10 deletions.
16 changes: 14 additions & 2 deletions examples/virtual_methods/cat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,19 @@ impl Default for Cat {
///
/// By convention we still create an empty `CatImpl` trait, this allows us to add
/// 'protected' cat methods only available to be called by other Cats later.
pub trait CatImpl: PetImpl {}
pub trait CatImpl: PetImpl
where
<Self as ObjectSubclass>::Type: IsA<glib::Object>,
<Self as ObjectSubclass>::Type: IsA<Pet>,
<Self as ObjectSubclass>::Type: IsA<Cat>,
{
}

/// To make this class subclassable we need to implement IsSubclassable
unsafe impl<Obj: CatImpl + PetImpl> IsSubclassable<Obj> for Cat {}
unsafe impl<Obj: CatImpl + PetImpl> IsSubclassable<Obj> for Cat
where
<Obj as ObjectSubclass>::Type: IsA<glib::Object>,
<Obj as ObjectSubclass>::Type: IsA<Pet>,
<Obj as ObjectSubclass>::Type: IsA<Cat>,
{
}
25 changes: 21 additions & 4 deletions examples/virtual_methods/pet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,11 @@ pub trait PetExt: IsA<Pet> {
impl<T: IsA<Pet>> PetExt for T {}

/// The `PetImpl` trait contains overridable virtual function definitions for [`Pet`] objects.
pub trait PetImpl: ObjectImpl {
pub trait PetImpl: ObjectImpl
where
<Self as ObjectSubclass>::Type: IsA<glib::Object>,
<Self as ObjectSubclass>::Type: IsA<Pet>,
{
/// Default implementation of a virtual method.
///
/// This always calls into the implementation of the parent class so that if
Expand All @@ -148,7 +152,11 @@ pub trait PetImpl: ObjectImpl {
/// The `PetImplExt` trait contains non-overridable methods for subclasses to use.
///
/// These are supposed to be called only from inside implementations of `Pet` subclasses.
pub trait PetImplExt: PetImpl {
pub trait PetImplExt: PetImpl
where
<Self as ObjectSubclass>::Type: IsA<glib::Object>,
<Self as ObjectSubclass>::Type: IsA<Pet>,
{
/// Chains up to the parent implementation of [`PetImpl::pet`]
fn parent_pet(&self) -> bool {
let data = Self::type_data();
Expand All @@ -169,10 +177,19 @@ pub trait PetImplExt: PetImpl {
}

/// The `PetImplExt` trait is implemented for all subclasses that have [`Pet`] in the class hierarchy
impl<T: PetImpl> PetImplExt for T {}
impl<T: PetImpl> PetImplExt for T
where
<Self as ObjectSubclass>::Type: IsA<glib::Object>,
<Self as ObjectSubclass>::Type: IsA<Pet>,
{
}

/// To make this class subclassable we need to implement IsSubclassable
unsafe impl<Obj: PetImpl> IsSubclassable<Obj> for Pet {
unsafe impl<Obj: PetImpl> IsSubclassable<Obj> for Pet
where
<Obj as ObjectSubclass>::Type: IsA<glib::Object>,
<Obj as ObjectSubclass>::Type: IsA<Pet>,
{
/// Override the virtual method function pointers in subclasses to call directly into the
/// `PetImpl` of the subclass.
///
Expand Down
25 changes: 21 additions & 4 deletions examples/virtual_methods/purrable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,11 @@ pub trait PurrableExt: IsA<Purrable> {
impl<T: IsA<Purrable>> PurrableExt for T {}

/// The `PurrableImpl` trait contains virtual function definitions for [`Purrable`] objects.
pub trait PurrableImpl: ObjectImpl {
pub trait PurrableImpl: ObjectImpl
where
<Self as ObjectSubclass>::Type: IsA<glib::Object>,
<Self as ObjectSubclass>::Type: IsA<Purrable>,
{
/// Return the current purring status.
///
/// The default implementation chains up to the parent implementation,
Expand All @@ -96,7 +100,11 @@ pub trait PurrableImpl: ObjectImpl {
/// The `PurrableImplExt` trait contains non-overridable methods for subclasses to use.
///
/// These are supposed to be called only from inside implementations of `Pet` subclasses.
pub trait PurrableImplExt: PurrableImpl {
pub trait PurrableImplExt: PurrableImpl
where
<Self as ObjectSubclass>::Type: IsA<glib::Object>,
<Self as ObjectSubclass>::Type: IsA<Purrable>,
{
/// Chains up to the parent implementation of [`PurrableExt::is_purring`]
fn parent_is_purring(&self) -> bool {
let data = Self::type_data();
Expand All @@ -109,10 +117,19 @@ pub trait PurrableImplExt: PurrableImpl {
}

/// The `PurrableImplExt` trait is implemented for all classes that implement [`Purrable`].
impl<T: PurrableImpl> PurrableImplExt for T {}
impl<T: PurrableImpl> PurrableImplExt for T
where
<Self as ObjectSubclass>::Type: IsA<glib::Object>,
<Self as ObjectSubclass>::Type: IsA<Purrable>,
{
}

/// To make this interface implementable we need to implement [`IsImplementable`]
unsafe impl<Obj: PurrableImpl> IsImplementable<Obj> for Purrable {
unsafe impl<Obj: PurrableImpl> IsImplementable<Obj> for Purrable
where
<Obj as ObjectSubclass>::Type: IsA<glib::Object>,
<Obj as ObjectSubclass>::Type: IsA<Purrable>,
{
fn interface_init(iface: &mut glib::Interface<Self>) {
let klass = iface.as_mut();

Expand Down

0 comments on commit 12d1877

Please sign in to comment.