Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

examples: Add stricter impl trait bounds #1518

Merged
merged 1 commit into from
Sep 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one is not inferred by requiring PetImpl, and PetImpl requiring IsA<Pet>?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is required, not inferred. Therefore it is showing an error if not specified.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

error[E0277]: the trait bound `<Self as glib::subclass::types::ObjectSubclass>::Type: glib::object::IsA<pet::Pet>` is not satisfied
   --> examples/virtual_methods/cat.rs:99:20
    |
99  | pub trait CatImpl: PetImpl
    |                    ^^^^^^^ the trait `glib::object::IsA<pet::Pet>` is not implemented for `<Self as glib::subclass::types::ObjectSubclass>::Type`
    |
note: required by a bound in `pet::PetImpl`
   --> examples/virtual_methods/pet.rs:130:37
    |
128 | pub trait PetImpl: ObjectImpl
    |           ------- required by a bound in this trait
129 | where
130 |     <Self as ObjectSubclass>::Type: IsA<Pet>,
    |                                     ^^^^^^^^ required by this bound in `PetImpl`
help: consider further restricting the associated type
    |
101 |     <Self as ObjectSubclass>::Type: IsA<Cat>, <Self as glib::subclass::types::ObjectSubclass>::Type: glib::object::IsA<pet::Pet>
    |                                             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

error[E0277]: the trait bound `<Obj as glib::subclass::types::ObjectSubclass>::Type: glib::object::IsA<pet::Pet>` is not satisfied
   --> examples/virtual_methods/cat.rs:106:28
    |
106 | unsafe impl<Obj: CatImpl + PetImpl> IsSubclassable<Obj> for Cat where
    |                            ^^^^^^^ the trait `glib::object::IsA<pet::Pet>` is not implemented for `<Obj as glib::subclass::types::ObjectSubclass>::Type`
    |
note: required by a bound in `pet::PetImpl`
   --> examples/virtual_methods/pet.rs:130:37
    |
128 | pub trait PetImpl: ObjectImpl
    |           ------- required by a bound in this trait
129 | where
130 |     <Self as ObjectSubclass>::Type: IsA<Pet>,
    |                                     ^^^^^^^^ required by this bound in `PetImpl`
help: consider further restricting the associated type
    |
107 |     <Obj as ObjectSubclass>::Type: IsA<Cat>, <Obj as glib::subclass::types::ObjectSubclass>::Type: glib::object::IsA<pet::Pet>
    |                                            +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

For more information about this error, try `rustc --explain E0277`.
error: could not compile `gtk-rs-examples` (bin "virtual_methods") due to 2 previous errors

<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
Loading