Skip to content

Commit

Permalink
enhance(core): use diagnostic::on_unimplemented on rustc 1.78 and n…
Browse files Browse the repository at this point in the history
…ewer for async commands with references (#11522)

* enhance(core): use `diagnostic::on_unimplemented` on rustc 1.78 and newer for async commands with references

* change file

* clippy

* clippy

* add TODO
  • Loading branch information
amrbashir authored Nov 5, 2024
1 parent 7af01ff commit 17c6952
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 0 deletions.
6 changes: 6 additions & 0 deletions .changes/enhance-async-commands-error.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"tauri": "patch:enhance"
"tauri-macros": "patch:enhance"
---

Enhance the error message when using `async` commands with a reference.
48 changes: 48 additions & 0 deletions crates/tauri-macros/src/command/wrapper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,9 +186,18 @@ pub fn wrapper(attributes: TokenStream, item: TokenStream) -> TokenStream {
// only implemented by `Result`. That way we don't exclude renamed result types
// which we wouldn't otherwise be able to detect purely from the token stream.
// The "error message" displayed to the user is simply the trait name.
//
// TODO: remove this check once our MSRV is high enough
let diagnostic = if is_rustc_at_least(1, 78) {
quote!(#[diagnostic::on_unimplemented(message = "async commands that contain references as inputs must return a `Result`")])
} else {
quote!()
};

async_command_check = quote_spanned! {return_type.span() =>
#[allow(unreachable_code, clippy::diverging_sub_expression)]
const _: () = if false {
#diagnostic
trait AsyncCommandMustReturnResult {}
impl<A, B> AsyncCommandMustReturnResult for ::std::result::Result<A, B> {}
let _check: #return_type = unreachable!();
Expand Down Expand Up @@ -452,3 +461,42 @@ fn parse_arg(
}
)))
}

fn is_rustc_at_least(major: u32, minor: u32) -> bool {
let version = rustc_version();
version.0 >= major && version.1 >= minor
}

fn rustc_version() -> (u32, u32) {
cross_command("rustc")
.arg("-V")
.output()
.ok()
.and_then(|o| {
let version = String::from_utf8_lossy(&o.stdout)
.trim()
.split(' ')
.nth(1)
.unwrap_or_default()
.split(".")
.take(2)
.flat_map(|p| p.parse::<u32>().ok())
.collect::<Vec<_>>();
version
.first()
.and_then(|major| version.get(1).map(|minor| (*major, *minor)))
})
.unwrap_or((1, 0))
}

fn cross_command(bin: &str) -> std::process::Command {
#[cfg(target_os = "windows")]
let cmd = {
let mut cmd = std::process::Command::new("cmd");
cmd.arg("/c").arg(bin);
cmd
};
#[cfg(not(target_os = "windows"))]
let cmd = std::process::Command::new(bin);
cmd
}

0 comments on commit 17c6952

Please sign in to comment.