Skip to content

Commit 17c6952

Browse files
authored
enhance(core): use diagnostic::on_unimplemented on rustc 1.78 and newer 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
1 parent 7af01ff commit 17c6952

File tree

2 files changed

+54
-0
lines changed

2 files changed

+54
-0
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"tauri": "patch:enhance"
3+
"tauri-macros": "patch:enhance"
4+
---
5+
6+
Enhance the error message when using `async` commands with a reference.

crates/tauri-macros/src/command/wrapper.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,9 +186,18 @@ pub fn wrapper(attributes: TokenStream, item: TokenStream) -> TokenStream {
186186
// only implemented by `Result`. That way we don't exclude renamed result types
187187
// which we wouldn't otherwise be able to detect purely from the token stream.
188188
// The "error message" displayed to the user is simply the trait name.
189+
//
190+
// TODO: remove this check once our MSRV is high enough
191+
let diagnostic = if is_rustc_at_least(1, 78) {
192+
quote!(#[diagnostic::on_unimplemented(message = "async commands that contain references as inputs must return a `Result`")])
193+
} else {
194+
quote!()
195+
};
196+
189197
async_command_check = quote_spanned! {return_type.span() =>
190198
#[allow(unreachable_code, clippy::diverging_sub_expression)]
191199
const _: () = if false {
200+
#diagnostic
192201
trait AsyncCommandMustReturnResult {}
193202
impl<A, B> AsyncCommandMustReturnResult for ::std::result::Result<A, B> {}
194203
let _check: #return_type = unreachable!();
@@ -452,3 +461,42 @@ fn parse_arg(
452461
}
453462
)))
454463
}
464+
465+
fn is_rustc_at_least(major: u32, minor: u32) -> bool {
466+
let version = rustc_version();
467+
version.0 >= major && version.1 >= minor
468+
}
469+
470+
fn rustc_version() -> (u32, u32) {
471+
cross_command("rustc")
472+
.arg("-V")
473+
.output()
474+
.ok()
475+
.and_then(|o| {
476+
let version = String::from_utf8_lossy(&o.stdout)
477+
.trim()
478+
.split(' ')
479+
.nth(1)
480+
.unwrap_or_default()
481+
.split(".")
482+
.take(2)
483+
.flat_map(|p| p.parse::<u32>().ok())
484+
.collect::<Vec<_>>();
485+
version
486+
.first()
487+
.and_then(|major| version.get(1).map(|minor| (*major, *minor)))
488+
})
489+
.unwrap_or((1, 0))
490+
}
491+
492+
fn cross_command(bin: &str) -> std::process::Command {
493+
#[cfg(target_os = "windows")]
494+
let cmd = {
495+
let mut cmd = std::process::Command::new("cmd");
496+
cmd.arg("/c").arg(bin);
497+
cmd
498+
};
499+
#[cfg(not(target_os = "windows"))]
500+
let cmd = std::process::Command::new(bin);
501+
cmd
502+
}

0 commit comments

Comments
 (0)