Property: trait unsatisfied - why?

Hello,

I created a property at a subclassed EntryRow for a RefCell<Option<url::Url>> which is from url - Rust.

When created, the compiler complains that the trait bound Default is not satisfied by my type (see above).

I guess this is because the URL crate does not implement that trait for the URL type it defines, right?
(I can replace the URL with a ‘gio::file’ for testing and that compiles. I guess that is because gio::file implements the trait Default)

How should I proceed?
I cannot implement the Default trait for URL in my crate, because the trait and the type are outside of my crate (last paragraph in Traits: Defining Shared Behavior - The Rust Programming Language).
Is the only thing I can do to wait/code/ask for the creation of the Default trait inside the URL repo and use a basic string as a replacement for a URL as long as it is missing?

Best wishes
Tobias

You don’t need to implement Default for url::Url. RefCell already implements Default if its content does, and Option<T> always implements Default.

Your problem is probably something else but without more code context and the actual compiler error message that’s hard to guess.

Thank you for taking the time.
That sounds good. I’d love to directly use a URL instead of a string.

Sure, the code follows.
One thing: I somehow have different missing traits than Default in the error messages right now and I am unable to find out why it was requesting Default before.
In general the issues are the same: missing trait implementations. Lets see, if you find something wrong here.

edit: I left out the Option<T> before. That is why it complained about missing Default trait. So the errors it shows now are the real ones I am fighting with

Compiler errors
warning: unused variable: `url`
  --> src/lib.rs:36:24
   |
36 | fn filter_music_source(url: Url) {
   |                        ^^^ help: if this is intentional, prefix it with an underscore: `_url`
   |
   = note: `#[warn(unused_variables)]` on by default

warning: function `filter_music_source` is never used
  --> src/lib.rs:36:4
   |
36 | fn filter_music_source(url: Url) {
   |    ^^^^^^^^^^^^^^^^^^^
   |
   = note: `#[warn(dead_code)]` on by default

warning: `dynamic-music-filter` (lib) generated 2 warnings
   Compiling dynamic-music-filter v0.1.0 (/home/tobiasb/DATA/Music/Loudness war/dynamic-music-filter)
error[E0277]: the trait bound `RefCell<std::option::Option<url::Url>>: libadwaita::glib::property::Property` is not satisfied
  --> src/ui/filter_row.rs:20:9
   |
20 |         #[property(get, set)]
   |         ^ the trait `libadwaita::glib::property::Property` is not implemented for `RefCell<std::option::Option<url::Url>>`
   |
   = help: the trait `libadwaita::glib::property::Property` is implemented for `RefCell<T>`

error[E0277]: the trait bound `RefCell<std::option::Option<url::Url>>: libadwaita::glib::property::Property` is not satisfied
  --> src/ui/filter_row.rs:14:33
   |
14 |     #[derive(CompositeTemplate, Properties, Default)]
   |                                 ^^^^^^^^^^ the trait `libadwaita::glib::property::Property` is not implemented for `RefCell<std::option::Option<url::Url>>`
   |
   = help: the trait `libadwaita::glib::property::Property` is implemented for `RefCell<T>`
   = note: this error originates in the derive macro `Properties` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the trait bound `RefCell<std::option::Option<url::Url>>: libadwaita::glib::property::Property` is not satisfied
  --> src/ui/window/mod.rs:56:45
   |
56 |                         self.imp().link_row.set_url(url.expect("Supported music source should have a url").as_str());
   |                                             ^^^^^^^ the trait `libadwaita::glib::property::Property` is not implemented for `RefCell<std::option::Option<url::Url>>`
   |
   = help: the trait `libadwaita::glib::property::Property` is implemented for `RefCell<T>`

error[E0277]: the trait bound `RefCell<std::option::Option<url::Url>>: libadwaita::glib::property::Property` is not satisfied
  --> src/ui/filter_row.rs:21:18
   |
21 |         pub url: RefCell<Option<Url>>,
   |                  ^^^^^^^^^^^^^^^^^^^^ the trait `libadwaita::glib::property::Property` is not implemented for `RefCell<std::option::Option<url::Url>>`
   |
   = help: the trait `libadwaita::glib::property::Property` is implemented for `RefCell<T>`

error[E0277]: the trait bound `url::Url: ToValueOptional` is not satisfied
  --> src/ui/filter_row.rs:14:33
   |
14 |     #[derive(CompositeTemplate, Properties, Default)]
   |                                 ^^^^^^^^^^ the trait `ToValueOptional` is not implemented for `url::Url`, which is required by `Value: From<&std::option::Option<url::Url>>`
   |
   = help: the following other types implement trait `ToValueOptional`:
             &T
             &VariantTy
             ATContext
             AboutDialog
             AboutWindow
             Accessible
             AccessibleRange
             Action
           and 703 others
   = note: required for `std::option::Option<url::Url>` to implement `ToValue`
   = note: required for `Value` to implement `From<&std::option::Option<url::Url>>`
   = note: this error originates in the derive macro `Properties` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the trait bound `url::Url: StaticType` is not satisfied
  --> src/ui/filter_row.rs:14:33
   |
14 |     #[derive(CompositeTemplate, Properties, Default)]
   |                                 ^^^^^^^^^^ the trait `StaticType` is not implemented for `url::Url`, which is required by `Value: From<&std::option::Option<url::Url>>`
   |
   = help: the following other types implement trait `StaticType`:
             &'a T
             &'a [GStringPtr]
             &'a mut T
             ()
             *mut c_void
             ATContext
             AboutDialog
             AboutWindow
           and 1048 others
   = note: required for `std::option::Option<url::Url>` to implement `ToValue`
   = note: required for `Value` to implement `From<&std::option::Option<url::Url>>`
   = note: this error originates in the derive macro `Properties` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the trait bound `url::Url: FromValue<'_>` is not satisfied
   --> src/ui/filter_row.rs:14:33
    |
14  |     #[derive(CompositeTemplate, Properties, Default)]
    |                                 ^^^^^^^^^^ the trait `FromValue<'_>` is not implemented for `url::Url`, which is required by `std::option::Option<url::Url>: FromValue<'_>`
    |
    = help: the following other types implement trait `FromValue<'a>`:
              `&'a ATContext` implements `FromValue<'a>`
              `&'a AboutDialog` implements `FromValue<'a>`
              `&'a AboutWindow` implements `FromValue<'a>`
              `&'a Accessible` implements `FromValue<'a>`
              `&'a AccessibleRange` implements `FromValue<'a>`
              `&'a Action` implements `FromValue<'a>`
              `&'a ActionBar` implements `FromValue<'a>`
              `&'a ActionGroup` implements `FromValue<'a>`
            and 1686 others
    = note: required for `std::option::Option<url::Url>` to implement `FromValue<'_>`
note: required by a bound in `Value::get`
   --> /home/tobiasb/.cargo/registry/src/index.crates.io-6f17d22bba15001f/glib-0.20.5/src/value.rs:576:12
    |
574 |     pub fn get<'a, T>(&'a self) -> Result<T, <<T as FromValue>::Checker as ValueTypeChecker>::Error>
    |            --- required by a bound in this associated function
575 |     where
576 |         T: FromValue<'a>,
    |            ^^^^^^^^^^^^^ required by this bound in `Value::get`
    = note: this error originates in the derive macro `Properties` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the trait bound `url::Url: StaticType` is not satisfied
   --> src/ui/filter_row.rs:14:33
    |
14  |     #[derive(CompositeTemplate, Properties, Default)]
    |                                 ^^^^^^^^^^ the trait `StaticType` is not implemented for `url::Url`, which is required by `std::option::Option<url::Url>: FromValue<'_>`
    |
    = help: the following other types implement trait `StaticType`:
              &'a T
              &'a [GStringPtr]
              &'a mut T
              ()
              *mut c_void
              ATContext
              AboutDialog
              AboutWindow
            and 1048 others
    = note: required for `std::option::Option<url::Url>` to implement `FromValue<'_>`
note: required by a bound in `Value::get`
   --> /home/tobiasb/.cargo/registry/src/index.crates.io-6f17d22bba15001f/glib-0.20.5/src/value.rs:576:12
    |
574 |     pub fn get<'a, T>(&'a self) -> Result<T, <<T as FromValue>::Checker as ValueTypeChecker>::Error>
    |            --- required by a bound in this associated function
575 |     where
576 |         T: FromValue<'a>,
    |            ^^^^^^^^^^^^^ required by this bound in `Value::get`
    = note: this error originates in the derive macro `Properties` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the trait bound `RefCell<std::option::Option<url::Url>>: libadwaita::glib::property::Property` is not satisfied
   --> src/ui/filter_row.rs:14:33
    |
14  |     #[derive(CompositeTemplate, Properties, Default)]
    |                                 ^^^^^^^^^^ the trait `libadwaita::glib::property::Property` is not implemented for `RefCell<std::option::Option<url::Url>>`
...
20  |         #[property(get, set)]
    |         - required by a bound introduced by this call
    |
    = help: the trait `libadwaita::glib::property::Property` is implemented for `RefCell<T>`
note: required by a bound in `std::convert::From::from`
   --> /home/tobiasb/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/convert/mod.rs:580:16
    |
580 | pub trait From<T>: Sized {
    |                ^ required by this bound in `From::from`
...
585 |     fn from(value: T) -> Self;
    |        ---- required by a bound in this associated function

For more information about this error, try `rustc --explain E0277`.
error: could not compile `dynamic-music-filter` (bin "dynamic-music-filter") due to 11 previous errors
src/ui/filter_row.rs
use adw::prelude::*;
use adw::subclass::prelude::*;
use adw::glib;

mod imp {
    use super::*;
    
    use glib::Properties;
    use adw::gtk::CompositeTemplate;
    use url::Url;
    use std::cell::RefCell;
    use adw::ExpanderRow;

    #[derive(CompositeTemplate, Properties, Default)]
    #[template(file = "filter_row.ui")]
    #[properties(wrapper_type = super::FilterRow)]
    pub struct FilterRow {
        #[property(get, set)]
        pub filter_results: RefCell<Option<ExpanderRow>>,
        #[property(get, set)]
        pub url: RefCell<Option<Url>>,
        
    }

    #[glib::object_subclass]
    impl ObjectSubclass for FilterRow {
        const NAME: &'static str = "FilterRow";
        type Type = super::FilterRow;
        type ParentType = adw::EntryRow;

        fn class_init(klass: &mut Self::Class) {
            klass.bind_template();
        }

        fn instance_init(obj: &glib::subclass::InitializingObject<Self>) {
            obj.init_template();
        }
    }

    #[glib::derived_properties]
    impl ObjectImpl for FilterRow {}

    impl WidgetImpl for FilterRow {}
    impl ListBoxRowImpl for FilterRow {}
    impl PreferencesRowImpl for FilterRow {}
    impl EntryRowImpl for FilterRow {}

    impl FilterRow {}
}

glib::wrapper! {
    pub struct FilterRow(ObjectSubclass<imp::FilterRow>)
        @extends adw::EntryRow, adw::PreferencesRow, gtk::ListBoxRow, gtk::Widget, gtk::Editable,
        @implements gtk::Accessible, gtk::Buildable, gtk::ConstraintTarget, gtk::Actionable;
}

impl FilterRow {
    pub fn new() -> Self {
        glib::Object::new()
    }

    pub fn reset(&self) {}
}
src/ui/filter_row.ui
<?xml version="1.0" encoding="UTF-8"?>
<interface>
  <requires lib="gtk" version="4.0"/>
  <requires lib="libadwaita" version="1.6"/>
  <template class="FilterRow" parent="AdwEntryRow">
    <property name="title">Music source link</property>
  </template>
</interface>

edit: added Cargo.toml file contents:

Cargo.toml
[package]
name = "dynamic-music-filter"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]

url = "2.5.3"
gtk = { version = "0.9", package = "gtk4", features = ["v4_12"] }

[dependencies.adw]
package = "libadwaita"
version = "0.7.1"
features = ["v1_2"]

[build-dependencies]
glib-build-tools = "0.20.0"

The FilterRow is stored as a template child in a subclassed window. Let me know if this code is needed, too. I left it out to not bloat this question more than needed.

If someone finds the time, please have a look at the compiler error messages I posted above.

I would like to know if I can fix this, or if it is a problem introduced by a dependency.

Best wishes
Tobias

According to the docs the set of types that can be used is restricted to types implementing the property trait.

I’m still not sure why a RefCell<Option<String>> works and a RefCell<Option<Url>> doesn’t, but that is a more general rust question and not specific to gtk-rs. So I’ll ask that in a rust forum.

As a good workaround for my problem and also for others with a similar problem, one can use the built-in types of glib as a replacement for types that don’t work as properties. I found a glib::Uri which is very similar to the URL crate. Storing such a Uri at a gtk-rs element like a window works because it satisfies the needed traits.
I still use the url::Url crate in my library and convert it to a glib::Uri to store it at the GUI application to keep the library free of glib dependencies.
Maybe that changes when the URL crate implements the needed traits.