linebender/druid-widget-nursery

Selector Widget error

giannissc opened this issue · 19 comments

the trait bound `Destination: druid::data::Data` is not satisfied
  --> src\main.rs:45:46
   |
45 |           Scroll::new(ListSelect::build_widget(vec![
   |  ______________________________________________^
46 | |             ("to Sydney", Destination::Sydney),
47 | |             ("to Petaluma", Destination::Petaluma),
48 | |             ("to Tokyo", Destination::Tokyo),
49 | |             ("to Paris", Destination::Paris),
50 | |         ]))
   | |_________^ the trait `druid::data::Data` is not implemented for `Destination`

This happens when extracting example and running it as an isolated instance @maan2003

Have you tried deriving Data for your type?

I have done so but when it didn't work I copied the example from nursury and it didn't work either.

dropdown_test.zip

Try replacing vec![..] with Arc::new(vec![..]). Data::same needs to run quickly, and so isn't implemented for Vec<_>, only for Arc<Vec<_>>

Is it compatible with the im crate as well?

So because im::Vector is immutable, using b-trees internally, it is as cheap to compare as Arc (a pointer equality check). So Data is implemented for im types.

Rather than import the im crate directly, it's best to turn on the im feature of druid and use the types that way, to ensure the version of im that has the traits implemented is the same as the one you're using. Version conflicts when using traits can lead to very confusing error messages.

Well I used vector but I am getting the following errors

error[E0277]: the trait bound `Destination: druid::data::Data` is not satisfied
  --> src\main.rs:46:37
   |
46 |           Scroll::new(ListSelect::new(vector![
   |  _____________________________________^
47 | |             ("to Sydney", Destination::Sydney),
48 | |             ("to Petaluma", Destination::Petaluma),
49 | |             ("to Tokyo", Destination::Tokyo),
50 | |             ("to Paris", Destination::Paris),
51 | |         ]))
   | |_________^ the trait `druid::data::Data` is not implemented for `Destination`
   | 
  ::: C:\Users\John\.cargo\git\checkouts\druid-widget-nursery-63e9f3f67c4f288a\5e4a8d7\src\list_select.rs:36:48
   |
36 |           values: impl IntoIterator<Item = (impl Into<LabelText<T>> + 'static, T)>,
   |                                                  ------------------ required by this bound in `ListSelect::<T>::new`
   |
   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the trait bound `impl druid::widget::widget::Widget<Destination>: druid::Widget<_>` is not satisfied
  --> src\main.rs:46:21
   |
46 |           Scroll::new(ListSelect::new(vector![
   |  _____________________^
47 | |             ("to Sydney", Destination::Sydney),
48 | |             ("to Petaluma", Destination::Petaluma),
49 | |             ("to Tokyo", Destination::Tokyo),
50 | |             ("to Paris", Destination::Paris),
51 | |         ]))
   | |__________^ the trait `druid::Widget<_>` is not implemented for `impl druid::widget::widget::Widget<Destination>`
   |
   = note: required by `Scroll::<T, W>::new`

error[E0599]: no method named `vertical` found for struct `Scroll<_, impl druid::widget::widget::Widget<Destination>>` in the current scope
  --> src\main.rs:52:10
   |
52 |         .vertical()
   |          ^^^^^^^^ method not found in `Scroll<_, impl druid::widget::widget::Widget<Destination>>`
   |
   = note: the method `vertical` exists but the following trait bounds were not satisfied:
           `impl druid::widget::widget::Widget<Destination>: druid::Widget<_>`

error[E0277]: the trait bound `Transportation: druid::data::Data` is not satisfied
  --> src\main.rs:58:29
   |
58 |           DropdownSelect::new(vector![
   |  _____________________________^
59 | |             ("by car", Transportation::Car),
60 | |             ("by train", Transportation::Train),
61 | |             ("by plane", Transportation::Plane),
62 | |             ("in a yellow submarine", Transportation::Submarine),
63 | |         ])
   | |_________^ the trait `druid::data::Data` is not implemented for `Transportation`
   | 
  ::: C:\Users\John\.cargo\git\checkouts\druid-widget-nursery-63e9f3f67c4f288a\5e4a8d7\src\dropdown_select.rs:43:48
   |
43 |           values: impl IntoIterator<Item = (impl Into<LabelText<T>> + 'static, T)> + Clone + 'static,
   |                                                  ------------------ required by this bound in `DropdownSelect::<T>::new`
   |
   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0599]: no method named `align_left` found for opaque type `impl druid::widget::widget::Widget<Transportation>` in the current scope
  --> src\main.rs:64:10
   |
64 |         .align_left()
   |          ^^^^^^^^^^ method not found in `impl druid::widget::widget::Widget<Transportation>`
   |
   = note: the method `align_left` exists but the following trait bounds were not satisfied:
           `impl druid::widget::widget::Widget<Transportation>: druid::Widget<_>`
           which is required by `impl druid::widget::widget::Widget<Transportation>: WidgetExt<_>`
           `&impl druid::widget::widget::Widget<Transportation>: druid::Widget<_>`
           which is required by `&impl druid::widget::widget::Widget<Transportation>: WidgetExt<_>`
           `&mut impl druid::widget::widget::Widget<Transportation>: druid::Widget<_>`
           which is required by `&mut impl druid::widget::widget::Widget<Transportation>: WidgetExt<_>`
   = help: items from traits can only be used if the trait is in scope
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
   |
15 | use druid::widget::widget_ext::WidgetExt;
   |

error: aborting due to 5 previous errors; 1 warning emitted

Some errors have detailed explanations: E0277, E0599.
For more information about an error, try `rustc --explain E0277`.
error: could not compile `dropdown_test`

Can you help me out @derekdreery ?

So your error messages mention that the trait Data is not implemented for your data types. Any data types that you use in druid need to have Data implemented for them. Fortunately you can just do use druid::Data and then #[derive(Data)] on your data types to get the impl.

The last error is there because you haven't done use druid::WidgetExt when you need to for the function you use.

But already have all that. This is a copy from the example of the widget

Here is the code:

// Copyright 2019 The Druid Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use druid::widget::{CrossAxisAlignment, Flex, Label, Scroll};
use druid::{AppLauncher, Data, Env, Insets, Lens, Widget, WidgetExt, WindowDesc};
use druid_widget_nursery::{DropdownSelect, ListSelect};
use druid::im::{vector};

#[derive(Clone, Copy, Data, Debug, PartialEq)]
enum Destination {
    Sydney,
    Petaluma,
    Tokyo,
    Paris,
}

//#[derive(Clone, Copy, Data, Debug, PartialEq)]
#[derive(Data, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug)]
enum Transportation {
    Car,
    Train,
    Plane,
    Submarine,
}

#[derive(Data, Clone, Lens)]
struct AppData {
    destination: Destination,
    transportation: Transportation,
}

fn main_widget() -> impl Widget<AppData> {
    let mut row = Flex::row().cross_axis_alignment(CrossAxisAlignment::Start);
    row.add_flex_child(
        Scroll::new(ListSelect::new(vector![
            ("to Sydney", Destination::Sydney),
            ("to Petaluma", Destination::Petaluma),
            ("to Tokyo", Destination::Tokyo),
            ("to Paris", Destination::Paris),
        ]))
        .vertical()
        .lens(AppData::destination),
        1.0,
    );
    row.add_default_spacer();
    row.add_flex_child(
        DropdownSelect::new(vector![
            ("by car", Transportation::Car),
            ("by train", Transportation::Train),
            ("by plane", Transportation::Plane),
            ("in a yellow submarine", Transportation::Submarine),
        ])
        .align_left()
        .lens(AppData::transportation),
        1.0,
    );

    let mut col = Flex::column().cross_axis_alignment(CrossAxisAlignment::Start);
    col.add_child(
        Label::new(|d: &AppData, _: &Env| {
            format!("Let's go to {:?} by {:?}", d.destination, d.transportation)
        })
        .padding(Insets::uniform_xy(5., 5.)),
    );
    col.add_child(row);
    col
}

fn main() {
    let main_window = WindowDesc::new(main_widget())
        .title("Select")
        .window_size((250., 300.));

    // create the initial app state
    let app_data = AppData {
        transportation: Transportation::Car,
        destination: Destination::Tokyo,
    };

    // start the application
    AppLauncher::with_window(main_window)
        .use_env_tracing()
        .launch(app_data)
        .expect("Failed to launch application");
}

Could you post a full version that you expect to work (ideally in a git repository I can clone). Also, you may get quicker (and more varied) answers at https://xi.zulipchat.com/

Hello, I came here with the same issue - I tried to use the DropdownSelect, and was met with an example that simply didn't work. The error the trait druid::data::Data is not implemented for Destination is particularly unhelpful, since to a casual observer, it seems to be quite explicitly derived:

#[derive(Clone, Copy, Data, Debug, PartialEq)]
enum Destination {
    Sydney,
    Petaluma,
    Tokyo,
    Paris,
}

So far most errors I've encountered with Rust have pointed me in a useful direction, but this one has me stumped - I have no clue where to even start digging, here, because the error points at a thing that seems to contradict everything I know about traits and derivation.

@giannissc I see you closed this without further comment, did you ever figure anything out here?

Hey @cincodenada I've re-opened the issue so we can discuss. I agree that the error looks very unhelpful. It's worth mentioning that this library is very much an 'experimental' one (very low barrier to additions), so problems like this are expected. I'm keen to fix problems as they come up, though! :)

Are you saying that you ran one of the examples and it failed to compile? If not, could you post your code somewhere (the code that doesn't work), so I can take a look at it. Or can I just look at the repo that @giannissc posted?

@giannissc I'm sorry I missed your post before where you posted the repo - I must have skipped the notification (very easily done IMO). If you're no longer interested feel free to unsubscribe from the issue.

The repository: giannissc/dropdown-widget-test @derekdreery

I was able to make it work with a simple patch.
diff --git a/Cargo.toml b/Cargo.toml
index 54b665d..ed9e399 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -7,5 +7,5 @@ edition = "2018"
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

 [dependencies]
-druid = { git = "https://github.com/linebender/druid.git", version = "0.7", features = ["im"]}
+druid = { git = "https://github.com/linebender/druid.git", rev = "0a82b127eac325c9c721364a5d81f1bfd931cb13", features = ["im"]}
 druid-widget-nursery = {git = "https://github.com/linebender/druid-widget-nursery.git"}
diff --git a/src/main.rs b/src/main.rs
index 1f78036..4d59a0f 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -90,7 +90,6 @@ fn main() {

     // start the application
     AppLauncher::with_window(main_window)
-        .use_env_tracing()
         .launch(app_data)
         .expect("Failed to launch application");
 }

Realistically, you would specify the git rev for both druid and druid-widget-nursery. But the important part is that you depend on druid directly in the same way druid-widget-nursery depends on it (same git repo / branch / rev exactly), otherwise you will pull in two versions of druid and the widgets from the nursery will implement the Data trait of a different druid than the one AppLauncher and such are used from.

You can check with cargo tree -d whether you have duplicate dependencies. Another possibility is running cargo tree -i druid, which will show your direct and indirect dependencies on the package, or raise an error if you have duplicate dependencies on that package specifically.

Ah, thank you! With two versions of druid in play explains the confounding error message makes a lot more sense, I've run into similar issues in other languages before and should have suspected something like that. I was indeed able to resolve the issue following what you did above, pinning the druid version to match the druid_widget_nursery version.

I expected the nursery to be a little finicky by nature, so I wasn't surprised that I ran into issues, I was just stumped, so thanks! I am still getting to know my way around Rust, especially the packaging intricacies, so I also appreciate the cargo tips!

I've opened #87 to try to make a note of this in the docs as suggested by @maan2003 on Zulip, I think I got the right Cargo.toml setup but please do give it a once-over. Thanks!

For those reading along in the future: there's further discussion of this issue in this Zulip thread, and the discussion around Arcs and vectors above seems to be a red herring in this case, the root issue ended up being the two versions of druid fighting with each other. The bits about vectors and immutability are useful if you're trying to use vectors as Data attributes, but in this case the vectors were just part of the widget's interface, and the data attributes themselves were simple enums.

Hmm, we pinned the druid version to avoid breakage when druid updates, but maybe it actually causes more harm than good. Maybe we should get rid of it, and put a note on the repo that because we track master, things might break. It would probably be less confusing for library users, and would certainly lead to less confusing error messages!

I think pinning is the right thing to do, otherwise it's hard to find out which version to downgrade to if druid-widget-nursery doesn't work the latest druid version.