specta-rs / tauri-specta

Completely typesafe Tauri commands
MIT License
368 stars 40 forks source link

The trait bound impl std::future::Future<Output = std::result::Result<std::vec::Vec<lib::prisma::user::Data>, std::string::String>>: specta::function::result::FunctionResult<_> is not satisfied #99

Closed niraj-khatiwada closed 4 months ago

niraj-khatiwada commented 5 months ago

I'm getting this error while trying to use Prisma Rust Client with tauri-specta.

error[E0277]: the trait bound `impl std::future::Future<Output = std::result::Result<std::vec::Vec<lib::prisma::user::Data>, std::string::String>>: specta::function::result::FunctionResult<_>` is not satisfied
   --> src/main.rs:10:1
    |
10  | #[specta::specta]
    | ^^^^^^^^^^^^^^^^^ the trait `specta::function::result::FunctionResult<_>` is not implemented for `impl std::future::Future<Output = std::result::Result<std::vec::Vec<lib::prisma::user::Data>, std::string::String>>`
...
34  |             tauri_specta::ts::builder().commands(tauri_specta::collect_commands![get_users]);
    |                                                  ------------------------------------------ in this macro invocation
    |
    = help: the following other types implement trait `specta::function::Function<TMarker>`:
              fn() -> TResult
              fn(T10) -> TResult
              fn(T2, T3, T4, T5, T6, T7, T8, T9, T10) -> TResult
              fn(T3, T4, T5, T6, T7, T8, T9, T10) -> TResult
              fn(T4, T5, T6, T7, T8, T9, T10) -> TResult
              fn(T5, T6, T7, T8, T9, T10) -> TResult
              fn(T6, T7, T8, T9, T10) -> TResult
              fn(T7, T8, T9, T10) -> TResult
            and 3 others
    = note: required for `fn(State<'_, Arc<PrismaClient>>) -> impl Future<Output = Result<Vec<Data>, String>>` to implement `specta::function::Function<_>`
    = note: the full type name has been written to '/home/niraj/Documents/rust/tauri/local-first-tauri/src-tauri/target/debug/deps/app-b89adf94dac85c84.long-type-5392976783934926372.txt'
note: required by a bound in `specta::internal::get_fn_datatype`
   --> /home/niraj/.cargo/registry/src/index.crates.io-6f17d22bba15001f/specta-2.0.0-rc.12/src/internal.rs:232:40
    |
232 |     pub fn get_fn_datatype<TMarker, T: Function<TMarker>>(
    |                                        ^^^^^^^^^^^^^^^^^ required by this bound in `get_fn_datatype`
    = note: this error originates in the macro `__specta__fn__get_users` which comes from the expansion of the macro `tauri_specta::collect_commands` (in Nightly builds, run with -Z macro-backtrace for more info)

image

Steps to reproduce:

niraj-khatiwada commented 5 months ago

I used the code from this starter example.

oscartbeaumont commented 4 months ago

This issue is due to your Specta versions not matching up. This error is pretty horrible I will look into improving that in a future release.

Prisma Client Rust 0.6.11 is using Specta 1.0.2 while your using Tauri Specta v2 which depends on Specta v2.

You will likely need to fork Prisma Client Rust and upgrade the Specta version to match or downgrade Tauri Specta to v1.

FlorianStasse commented 4 months ago

I seem to have the same issue with the following command:

#[tauri::command]
#[specta::specta]
pub async fn register_event<R: Runtime>(app: AppHandle<R>, event: String) -> Result<()> {
    app.grpc().register_event(event).await
}

I pinned tauri, specta and tauri-specta to those versions in my workspace:

tauri = { version = "=2.0.0-beta.22" }
specta = { version = "=2.0.0-rc.12" }
tauri-specta = { version = "=2.0.0-rc.11" }

And use those features in my plugin package:

tauri = { workspace = true, features = ["specta"] }
specta = { workspace = true, features = ["function"] }
tauri-specta = { workspace = true, features = ["typescript"] }

But I have this error when compiling:

❯ cargo check
    Checking tauri-plugin-grpc v0.0.0 (/home/florian/Repos/admiral/crates/tauri-plugin-grpc)
error[E0277]: the trait bound `impl Future<Output = std::result::Result<(), error::Error>>: function::result::FunctionResult<_>` is not sati
   --> crates/tauri-plugin-grpc/src/commands.rs:23:1
    |
23  | #[specta::specta]
    | ^^^^^^^^^^^^^^^^^ the trait `function::result::FunctionResult<_>` is not implemented for `impl Future<Output = std::result::Result<(),
    |
   ::: crates/tauri-plugin-grpc/src/lib.rs:42:23
    |
42  |             .commands(tauri_specta::collect_commands![commands::register_event,]); // <- Each of your commands
    |                       ---------------------------------------------------------- in this macro invocation
    |
    = help: the following other types implement trait `Function<TMarker>`:
              fn() -> TResult
              fn(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) -> TResult
              fn(T2, T3, T4, T5, T6, T7, T8, T9, T10) -> TResult
              fn(T3, T4, T5, T6, T7, T8, T9, T10) -> TResult
              fn(T4, T5, T6, T7, T8, T9, T10) -> TResult
              fn(T5, T6, T7, T8, T9, T10) -> TResult
              fn(T6, T7, T8, T9, T10) -> TResult
              fn(T7, T8, T9, T10) -> TResult
            and 3 others
    = note: required for `fn(AppHandle<_>, std::string::String) -> impl Future<Output = std::result::Result<(), error::Error>>` to implement `Function<_>`
note: required by a bound in `get_fn_datatype`
   --> /home/florian/.cargo/registry/src/index.crates.io-6f17d22bba15001f/specta-2.0.0-rc.12/src/internal.rs:232:40
    |
232 |     pub fn get_fn_datatype<TMarker, T: Function<TMarker>>(
    |                                        ^^^^^^^^^^^^^^^^^ required by this bound in `get_fn_datatype`
    = note: this error originates in the macro `commands::__specta__fn__register_event` which comes from the expansion of the macro `tauri_specta::collect_commands` (in Nightly builds, run with -Z macro-backtrace for more info)

As I'm not using any other packages depending on specta, I don't think it comes from an issue with some versions of specta not matching. Do you have any idea about where this issue comes from ?

Brendonovich commented 4 months ago

@FlorianStasse Does error::Error implement specta::Type? tauri-specta v2 requires everything you return from a command to implement it.

FlorianStasse commented 4 months ago

@Brendonovich Thanks for the insight, I forgot about this type. I added the required `#[derive(specta::Type)]" to my type.

But it now seems that the generic in my commands is triggering a new error, and I can't find an example online of someone using tauri-specta with this kind of generic:

error[E0283]: type annotations needed
  --> crates/tauri-plugin-grpc/src/commands.rs:23:1
   |
23 |   #[specta::specta]
   |   ^^^^^^^^^^^^^^^^^ cannot infer type
   |
  ::: crates/tauri-plugin-grpc/src/lib.rs:41:60
   |
44 |           let builder = tauri_specta::ts::builder().commands(tauri_specta::collect_commands![
   |  ____________________________________________________________-
45 | |             commands::register_event,
46 | |         ]); // <- Each of your commands
   | |_________- in this macro invocation
   |
   = note: cannot satisfy `_: tauri::Runtime`
note: required by a bound in `register_event`
  --> crates/tauri-plugin-grpc/src/commands.rs:24:32
   |
24 | pub async fn register_event<R: Runtime>(app: AppHandle<R>, event: String) -> Result<()> {
   |                                ^^^^^^^ required by this bound in `register_event`
   = note: this error originates in the macro `commands::__specta__fn__register_event` which comes from the expansion of the macro `tauri_specta::collect_commands` (in Nightly builds, run with -Z macro-backtrace for more info)
Brendonovich commented 4 months ago

@FlorianStasse See the custom plugin example for where that generic comes from. It should be inferred via invoke_handler.

FlorianStasse commented 4 months ago

@Brendonovich Thanks for your quick replies, I cloned the repository and went to the plugin example to implement a function with the same signature as mine:

// Uses the app handle for something
#[tauri::command]
#[specta::specta]
async fn use_app_handle<R: tauri::Runtime>(_app: tauri::AppHandle<R>) {}

// We recommend re-using the builder via a macro rather than function as the builder's
// generics can be tricky to deal with
macro_rules! specta_builder {
    () => {
        ts::builder()
            .commands(collect_commands![add_numbers, use_app_handle])
            .events(collect_events![RandomNumber])
    };
}

But running cargo check still shows an error:

error[E0283]: type annotations needed
  --> examples/custom-plugin/plugin/src/lib.rs:19:1
   |
19 | #[specta::specta]
   | ^^^^^^^^^^^^^^^^^ cannot infer type
...
36 |         specta_builder!().build_plugin_utils(PLUGIN_NAME).unwrap();
   |         ----------------- in this macro invocation
   |
   = note: cannot satisfy `_: tauri::Runtime`
note: required by a bound in `use_app_handle`
  --> examples/custom-plugin/plugin/src/lib.rs:20:28
   |
20 | async fn use_app_handle<R: tauri::Runtime>(_app: tauri::AppHandle<R>) {}
   |                            ^^^^^^^^^^^^^^ required by this bound in `use_app_handle`
   = note: this error originates in the macro `__specta__fn__use_app_handle` which comes from the expansion of the macro `specta_builder` (in Nightly builds, run with -Z macro-backtrace for more info)

For more information about this error, try `rustc --explain E0283`.
error: could not compile `tauri-plugin-specta-example` (lib) due to 1 previous error

If the code snippet from above is not enough, I can fork the repository and push the modified plugin example that triggers this error.

Brendonovich commented 4 months ago

Oh, the command has a runtime generic. Didn't notice that. You'll need to hardcode the generic like this.

image
FlorianStasse commented 4 months ago

Thanks for you help, I was able to fix everything !