tauri-apps / tauri

Build smaller, faster, and more secure desktop and mobile applications with a web frontend.
https://tauri.app
Apache License 2.0
83.66k stars 2.51k forks source link

Compile error for async stateful commands that don't return a `Result` #2533

Open probablykasper opened 3 years ago

probablykasper commented 3 years ago

Describe the bug

Stateful async commands that don't return a Result give a compiler error.

To Reproduce

Example:

#[command]
pub async fn get_info(app: State<'_, Data>) -> bool {
  true
}

There's no error if you remove async, remove the app argument, or change the return type to a Result works.

Platform and Versions

Details ``` Operating System - Mac OS, version 10.15.7 X64 Node.js environment Node.js - 14.16.0 @tauri-apps/cli - 1.0.0-beta.10 @tauri-apps/api - 1.0.0-beta.8 Global packages npm - 6.14.11 yarn - 1.22.10 Rust environment rustc - 1.54.0 cargo - 1.54.0 App directory structure /node_modules /src-tauri /build /.git /src App tauri.rs - 1.0.0-beta.8 build-type - bundle CSP - default-src blob: data: filesystem: ws: wss: http: https: tauri: 'unsafe-eval' 'unsafe-inline' 'self' img-src: 'self' distDir - ../build devPath - http://localhost:8000 framework - Svelte ```

Stack Trace

error[E0597]: `__tauri_message__` does not live long enough
  --> src/cmd.rs:93:1
   |
93 |   #[command]
   |   ^^^^^^^^^-
   |   |        |
   |   |        `__tauri_message__` dropped here while still borrowed
   |   borrowed value does not live long enough
   |   argument requires that `__tauri_message__` is borrowed for `'static`
zsmatrix62 commented 2 years ago

same problem

ricardomatias commented 2 years ago

Is there any interim solution?

FabianLars commented 2 years ago

For now you just have to return a Result. If you don't want to return anything from the command it can be as simple as Result<(), ()> or in case of the OP's example it'd be Result<bool, ()>.

This doesn't change what you'll receive on the JavaScript side. Ok will resolve the Promise and Err will reject it.

willcrichton commented 1 month ago

If you have an async function that takes a State<'_, T> as input and returns a Result<(), String>, what are the conditions under which Tauri will return an Err? Is it if the frontend tries to call two commands that both request State<'_, T> simultaneously?

FabianLars commented 1 month ago

Just to be clear, this Result<(), String> can really only return errors from your code inside the function.

Errors from "outside" of that can be caused by missing function arguments for example. If the T in State is incorrect / not managed yet i think it panics instead of returning an error but not entirely sure. If the command is part of a plugin, tauri will also return an error on permission errors.

Calling the same command twice at the same time / in quick succession should not be an issue by itself.

willcrichton commented 1 month ago

Oh, I misunderstood. A different question then: why is State<'_, T> allowed as an input to an async command only if the function returns a Result<_, String>? Why not allow borrowed inputs to async commands with non-result return types?

FabianLars commented 1 month ago

Because Rust requires the Result to figure out the lifetimes for borrowed inputs in async commands and/or we don't know how to fix/workaround it without a Result.

I don't know, or at least can't remember, why exactly a Result (and more or less nothing else) fixes it.