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

Compilation error when using non-Copy types in messages #303

Closed
msrd0 opened this issue Dec 29, 2022 · 7 comments
Closed

Compilation error when using non-Copy types in messages #303

msrd0 opened this issue Dec 29, 2022 · 7 comments

Comments

@msrd0
Copy link
Contributor

msrd0 commented Dec 29, 2022

Whenever I have a message type that is non-Copy, e.g.

#[derive(Msg)]
pub enum Msg {
    MyEvent(String)
}

Then I cannot use this message, or otherwise I get a compilation error:

use my_widget::{MyWidget, Msg::MyEvent as MyWidgetMyEvent};

view! {
    // ...
    MyWidget() {
        MyWidgetMyEvent(foo) => Msg::MyEvent(foo)
    }
    // ...
}

The error message is

error[E0507]: cannot move out of `msg` as enum variant `MyEvent` which is behind a shared reference
   --> src/ui/mod.rs:XXX:Y
    |
XXX |                 MyWidget() {
    |                 ^^^^^^^^ help: consider removing the `&`: `$message`
...
XXX |                     MyWidgetMyEvent(foo) => Msg::MyEvent(foo)
    |                                     ---  data moved here

This is impossible to fix in user code, using e.g. Msg::MyEvent(foo.clone()) or Msg::MyEvent((&*foo).into()) produces the exact same error message. The problem is within the macro-generated code that produces &MyWidgetMyEvent(foo). I believe this could be fixed by emiting &MyWidgetMyEvent(ref foo), but I haven't tested that.

@antoyo
Copy link
Owner

antoyo commented Dec 30, 2022

You have to add ref before foo in MyWidgetMyEvent(foo) like in MyWidgetMyEvent(ref foo).

See this example.

@msrd0
Copy link
Contributor Author

msrd0 commented Dec 30, 2022

Is there a reason why you force the & in the relm::connect_stream! macro? It seems to compile just fine when the & is removed.

@antoyo
Copy link
Owner

antoyo commented Dec 30, 2022

I'm not sure exactly where & you're talking about, but I think I understand your question anyway.

Both the current widget and parent widgets can see the same message. The current widget gets an owned version of the event, but to avoid a clone, the parent widgets get a reference.

@msrd0
Copy link
Contributor Author

msrd0 commented Dec 30, 2022

I'm talking about this one: https://docs.rs/relm/0.24.0/src/relm/macros.rs.html#113. It is the source for the &$message part in the error message.

As far as I understand it, the parameter passed by observe is already borrowed, so match msg will match a reference anyways. I tried removing the & and at least for my code, it works without any problems and I don't need the ref. Compiling all your tests is really annoying as all of them compile into their own target folder which takes forever, so I didn't try.

@antoyo
Copy link
Owner

antoyo commented Dec 30, 2022

Oh, that's because of match ergonomics: the Rust compiler automatically adds the & and ref for you.

I find this leads to worse error messages which is why I prefer to avoid it.

@msrd0
Copy link
Contributor Author

msrd0 commented Dec 30, 2022

Well, it doesn't add the ref if you manually add the &, so I feel like right now it creates error messages where it would otherwise compile.

There might be other cases where this isn't the case that I just haven't found yet of course.

@antoyo
Copy link
Owner

antoyo commented Dec 30, 2022

Well, it doesn't add the ref if you manually add the &, so I feel like right now it creates error messages where it would otherwise compile.

Indeed, Rust won't do match ergonomics if you add * or &. That's the reason & is used in the macro: I wanted to disable match ergonomics.

@antoyo antoyo closed this as completed Sep 21, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants