serenity-rs / poise

Discord bot command framework for serenity, with advanced features like edit tracking and flexible argument parsing
MIT License
644 stars 114 forks source link

the trait bound `poise::serenity_prelude::Context: AsRef<poise::serenity_prelude::Context>` is not satisfied #247

Open sarahkittyy opened 7 months ago

sarahkittyy commented 7 months ago

What is this error? I am trying to use poise::execute_modal_on_component_interaction.

Here is my function:

pub async fn dispatch(ctx: &serenity::Context, mci: &ComponentInteraction) -> Result<(), Error> {
    match mci.data.custom_id.as_str() {
        "birthday.submit" => {
            let data: Option<AgeModal> =
                poise::execute_modal_on_component_interaction(ctx, mci.clone(), None, None).await?;
        }
        _ => (),
    }
    Ok(())
}

And my error is:

error[E0277]: the trait bound `poise::serenity_prelude::Context: AsRef<poise::serenity_prelude::Context>` is not satisfied
   --> src\discord\on_component_interaction.rs:12:63
    |
12  |                 poise::execute_modal_on_component_interaction(ctx, mci.clone(), None, None).await?;
    |                 --------------------------------------------- ^^^ the trait `AsRef<poise::serenity_prelude::Context>` is not implemented for `poise::serenity_prelude::Context`
    |                 |
    |                 required by a bound introduced by this call
    |
    = help: the following other types implement trait `AsRef<T>`:
              <poise::serenity_prelude::Context as AsRef<Arc<Cache>>>
              <poise::serenity_prelude::Context as AsRef<Arc<poise::serenity_prelude::Http>>>
              <poise::serenity_prelude::Context as AsRef<Cache>>
              <poise::serenity_prelude::Context as AsRef<ShardMessenger>>
              <poise::serenity_prelude::Context as AsRef<poise::serenity_prelude::Http>>
    = note: required for `&poise::serenity_prelude::Context` to implement `AsRef<poise::serenity_prelude::Context>`
note: required by a bound in `execute_modal_on_component_interaction`
   --> C:\Users\sarah\.cargo\registry\src\index.crates.io-6f17d22bba15001f\poise-0.6.1\src\modal.rs:123:15
    |
122 | pub async fn execute_modal_on_component_interaction<M: Modal>(
    |              -------------------------------------- required by a bound in this function
123 |     ctx: impl AsRef<serenity::Context>,
    |               ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `execute_modal_on_component_interaction`

For more information about this error, try `rustc --explain E0277`.
error: could not compile `girlpound-bot` (bin "girlpound-bot") due to 1 previous error

What is happening? I know in general there is no blanket impl AsRef<T> for &T in Rust because of some sort of conflict, but what do I do in this case? I feel like I am missing something obvious.

kangalio commented 7 months ago

It's possible your Cargo.toml contains a different serenity version than the one poise uses, which means the two mismatching serenity Context types only mismatch because they're of two different versions.. Poise 0.6 needs Serenity 0.12. Is that the case in your Cargo.toml?

sarahkittyy commented 7 months ago

There is no serenity in my Cargo.toml. I am using the one that comes in the poise crate. The types are the same. Rust does not have a blanket impl AsRef<T> for &T. To solve this I had to implement execute_model_generic myself.

sarahkittyy commented 7 months ago

@kangalio See https://doc.rust-lang.org/std/convert/trait.AsRef.html#reflexivity

GnomedDev commented 7 months ago

Please attach your Cargo.lock file, so we can see if you have duplicate dependencies.

sarahkittyy commented 7 months ago

Here. Poise 0.6.1 and Serenity 0.12.1. Cargo.lock.txt

The problem is not duplicate dependencies. The types are the same. AsRef<poise::serenity_prelude::Context> is NOT implemented for poise::serenity_prelude::Context. This is a known quirk of the rust language.

See https://doc.rust-lang.org/std/convert/trait.AsRef.html#reflexivity Also see this minimal example

To fix this I copied the existing but private execute_modal_generic here into my own code.

sarahkittyy commented 7 months ago

I'm not a Rust pro but maybe this should be impl Into<> or Deref<> or Borrow<> instead? Or maybe impl CacheHttp.

GnomedDev commented 7 months ago

It shouldn't be AsRef in the first place, it should just be &serenity::Context, I'll make that change now. Anyway, for now can't you just pass &serenity::Context?

sarahkittyy commented 7 months ago

No! You cannot pass &serenity::Context to a parameter of type impl AsRef<serenity::Context> because as per my last comments, &T does not implement the trait AsRef<T>. You would think it would, but it doesn't. See https://doc.rust-lang.org/std/convert/trait.AsRef.html#reflexivity.

Changing execute_modal_on_component_interaction's first argument to &serenity::Context instead of impl AsRef<serenity::Context> will fix this issue. Thanks ^^

GnomedDev commented 7 months ago

That is so weird.