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

Dowgrade/Upgrade not ususable in traits #1322

Open
gdesmott opened this issue Mar 5, 2024 · 2 comments
Open

Dowgrade/Upgrade not ususable in traits #1322

gdesmott opened this issue Mar 5, 2024 · 2 comments
Labels

Comments

@gdesmott
Copy link
Contributor

gdesmott commented Mar 5, 2024

trait Mytrait: Downgrade {
    fn mushroom(&self) {
        let weak = self.downgrade();
        let this = weak.upgrade().unwrap();
        this.snake();
    }

    fn snake(&self) {}
}

fails with:

error[E0599]: no method named `snake` found for associated type `<<Self as Downgrade>::Weak as Upgrade>::Strong` in the current scope
   --> glib/src/clone.rs:116:14
    |
116 |         this.snake();
    |              ^^^^^ method not found in `<<Self as Downgrade>::Weak as Upgrade>::Strong`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
note: `Mytrait` defines an item `snake`, perhaps you need to implement it
   --> glib/src/clone.rs:112:1
    |
112 | trait Mytrait: Downgrade {
    | ^^^^^^^^^^^^^^^^^^^^^^^^

I tried adding a bound tying back Upgrade::Strong with the trait but that doesn't work either:

trait Mytrait: Downgrade
where
    <<Self as Downgrade>::Weak as Upgrade>::Strong: Mytrait,
{
    fn mushroom(&self) {
        let weak = self.downgrade();
        let this = weak.upgrade().unwrap();
        this.snake();
    }

    fn snake(&self) {}
}
error[E0277]: the trait bound `<<<<Self as Downgrade>::Weak as Upgrade>::Strong as Downgrade>::Weak as Upgrade>::Strong: Mytrait` is not satisfied
   --> glib/src/clone.rs:114:53
    |
114 |     <<Self as Downgrade>::Weak as Upgrade>::Strong: Mytrait,
    |                                                     ^^^^^^^ the trait `Mytrait` is not implemented for `<<<<Self as Downgrade>::Weak as Upgrade>::Strong as Downgrade>::Weak as Upgrade>::Strong`
    |
note: required by a bound in `Mytrait`
   --> glib/src/clone.rs:114:53
    |
112 | trait Mytrait: Downgrade
    |       ------- required by a bound in this trait
113 | where
114 |     <<Self as Downgrade>::Weak as Upgrade>::Strong: Mytrait,
    |                                                     ^^^^^^^ required by this bound in `Mytrait`
    = note: `Mytrait` is a "sealed trait", because to implement it you also need to implement `clone::Mytrait`, which is not accessible; this is usually done to force you to use one of the provided types that already implement it
help: consider further restricting the associated type
    |
114 |     <<Self as Downgrade>::Weak as Upgrade>::Strong: Mytrait, <<<<Self as Downgrade>::Weak as Upgrade>::Strong as Downgrade>::Weak as Upgrade>::Strong: Mytrait
    |                                                            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Is there a way to make this work easily?

@gdesmott
Copy link
Contributor Author

gdesmott commented Mar 5, 2024

Here is a standalone version of the problem for easier testing:

trait Downgrade
where
    Self: Sized,
{
    type Weak: Upgrade;

    fn downgrade(&self) -> Self::Weak;
}

trait Upgrade
where
    Self: Sized,
{
    type Strong;

    fn upgrade(&self) -> Option<Self::Strong>;
}

trait Mytrait: Downgrade {
    fn mushroom(&self) {
        let weak = self.downgrade();
        let this = weak.upgrade().unwrap();
        this.snake();
    }

    fn snake(&self) {}
}

fn main() {}

@zachs18
Copy link
Contributor

zachs18 commented Mar 11, 2024

Library-level, the signature for Downgrade could be changed to have type Weak: Upgrade<Strong = Self>; instead of just type Weak: Upgrade;. (Are there are any cases where Self::Weak::Strong isn't Self?) (see below)

As for user-level workarounds, you can add a where Self::Weak: Upgrade<Strong = Self> to your trait, e.g.

trait Mytrait: Downgrade where Self::Weak: Upgrade<Strong = Self> {
    fn mushroom(&self) {
        let weak = self.downgrade();
        let this: Self = weak.upgrade().unwrap();
        this.snake();
    }

    fn snake(&self) {}
}

Ah, no the library-level change won't work (as-is at least), since &T where T: Downgrade implements Downgrade, and you obviously can't get a &T back out of that.

errors when applying the naive change to `glib`
error[E0271]: type mismatch resolving `<<T as Downgrade>::Weak as Upgrade>::Strong == &T`
  --> glib/src/clone.rs:57:17
   |
56 | impl<T: Downgrade> Downgrade for &T {
   |      - found this type parameter
57 |     type Weak = T::Weak;
   |                 ^^^^^^^ expected `&T`, found type parameter `T`
   |
   = note:   expected reference `&_`
           found type parameter `_`
note: required by a bound in `Downgrade::Weak`
  --> glib/src/clone.rs:18:24
   |
18 |     type Weak: Upgrade<Strong = Self>;
   |                        ^^^^^^^^^^^^^ required by this bound in `Downgrade::Weak`

error[E0271]: type mismatch resolving `<<T as Downgrade>::Weak as Upgrade>::Strong == BorrowedObject<'a, T>`
    --> glib/src/object.rs:4426:17
     |
4423 | impl<'a, T: crate::clone::Downgrade + ObjectType> crate::clone::Downgrade
     |          - found this type parameter
...
4426 |     type Weak = <T as crate::clone::Downgrade>::Weak;
     |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `BorrowedObject<'_, T>`, found type parameter `T`
     |
     = note:      expected struct `BorrowedObject<'a, T>`
             found type parameter `T`
note: required by a bound in `Downgrade::Weak`
    --> glib/src/clone.rs:18:24
     |
18   |     type Weak: Upgrade<Strong = Self>;
     |                        ^^^^^^^^^^^^^ required by this bound in `Downgrade::Weak`

error[E0271]: type mismatch resolving `<ObjectImplWeakRef<BoxedAnyObject> as Upgrade>::Strong == BoxedAnyObject`
   --> glib/src/boxed_any_object.rs:37:5
    |
37  |     #[glib::object_subclass]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `<ObjectImplWeakRef<BoxedAnyObject> as Upgrade>::Strong == BoxedAnyObject`
    |
note: expected this to be `imp::BoxedAnyObject`
   --> glib/src/subclass/object_impl_ref.rs:157:19
    |
157 |     type Strong = ObjectImplRef<T>;
    |                   ^^^^^^^^^^^^^^^^
    = note: expected struct `imp::BoxedAnyObject`
               found struct `ObjectImplRef<imp::BoxedAnyObject>`
note: required by a bound in `Downgrade::Weak`
   --> glib/src/clone.rs:18:24
    |
18  |     type Weak: Upgrade<Strong = Self>;
    |                        ^^^^^^^^^^^^^ required by this bound in `Downgrade::Weak`
    = note: this error originates in the attribute macro `glib::object_subclass` (in Nightly builds, run with -Z macro-backtrace for more info)

For more information about this error, try `rustc --explain E0271`.
error: could not compile `glib` (lib) due to 3 previous errors
warning: build failed, waiting for other jobs to finish...
error: could not compile `glib` (lib) due to 3 previous errors

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants