oscartbeaumont / tauri-specta

Completely typesafe Tauri commands
MIT License
289 stars 26 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 weeks ago

niraj-khatiwada commented 1 month 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 1 month ago

I used the code from this starter example.

oscartbeaumont commented 1 month 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 weeks 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 weeks ago

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

FlorianStasse commented 4 weeks 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 weeks ago

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

FlorianStasse commented 4 weeks 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 weeks 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 weeks ago

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