From 86e4b5a2b706aa60ec7f20f65099c1090444fc3d Mon Sep 17 00:00:00 2001 From: Chris Wailes Date: Mon, 12 Dec 2022 15:45:51 -0800 Subject: Upgrade tokio-macros to 1.8.2 This project was upgraded with external_updater. Usage: tools/external_updater/updater.sh update rust/crates/tokio-macros For more info, check https://cs.android.com/android/platform/superproject/+/master:tools/external_updater/README.md Test: TreeHugger Bug: 262591027 Change-Id: I97749cc2647467a8d85b51a699a406916d1ece99 --- .cargo_vcs_info.json | 2 +- Android.bp | 2 +- CHANGELOG.md | 28 +++++++- Cargo.toml | 12 +++- Cargo.toml.orig | 6 +- LICENSE | 2 +- METADATA | 12 ++-- src/entry.rs | 116 +++++++++++++++++++++++------- src/lib.rs | 199 ++++++++++++++++++++++++++++++++++++++++++++------- 9 files changed, 313 insertions(+), 66 deletions(-) diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json index 13f94be..6e0797d 100644 --- a/.cargo_vcs_info.json +++ b/.cargo_vcs_info.json @@ -1,6 +1,6 @@ { "git": { - "sha1": "f64673580dfc649954eb744eb2734f2f118baa47" + "sha1": "993a60b7c79b6fbdad872c6a173c2e6fe42b117f" }, "path_in_vcs": "tokio-macros" } \ No newline at end of file diff --git a/Android.bp b/Android.bp index 47abc03..3674182 100644 --- a/Android.bp +++ b/Android.bp @@ -22,7 +22,7 @@ rust_proc_macro { name: "libtokio_macros", crate_name: "tokio_macros", cargo_env_compat: true, - cargo_pkg_version: "1.7.0", + cargo_pkg_version: "1.8.2", srcs: ["src/lib.rs"], edition: "2018", rustlibs: [ diff --git a/CHANGELOG.md b/CHANGELOG.md index 633b43f..93d52e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,32 @@ +# 1.8.2 (November 30th, 2022) + +- fix a regression introduced in 1.8.1 ([#5244]) + +[#5244]: https://github.com/tokio-rs/tokio/pull/5244 + +# 1.8.1 (November 29th, 2022) + +(yanked) + +- macros: Pin Futures in `#[tokio::test]` to stack ([#5205]) +- macros: Reduce usage of last statement spans in proc-macros ([#5092]) +- macros: Improve the documentation for `#[tokio::test]` ([#4761]) + +[#5205]: https://github.com/tokio-rs/tokio/pull/5205 +[#5092]: https://github.com/tokio-rs/tokio/pull/5092 +[#4761]: https://github.com/tokio-rs/tokio/pull/4761 + +# 1.8.0 (June 4th, 2022) + +- macros: always emit return statement ([#4636]) +- macros: support setting a custom crate name for `#[tokio::main]` and `#[tokio::test]` ([#4613]) + +[#4613]: https://github.com/tokio-rs/tokio/pull/4613 +[#4636]: https://github.com/tokio-rs/tokio/pull/4636 + # 1.7.0 (December 15th, 2021) -- macros: address remainging clippy::semicolon_if_nothing_returned warning ([#4252]) +- macros: address remaining `clippy::semicolon_if_nothing_returned` warning ([#4252]) [#4252]: https://github.com/tokio-rs/tokio/pull/4252 diff --git a/Cargo.toml b/Cargo.toml index a2342b9..04bfa41 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,20 +11,25 @@ [package] edition = "2018" -rust-version = "1.46" +rust-version = "1.49" name = "tokio-macros" -version = "1.7.0" +version = "1.8.2" authors = ["Tokio Contributors "] -description = "Tokio's proc macros.\n" +description = """ +Tokio's proc macros. +""" homepage = "https://tokio.rs" +readme = "README.md" categories = ["asynchronous"] license = "MIT" repository = "https://github.com/tokio-rs/tokio" + [package.metadata.docs.rs] all-features = true [lib] proc-macro = true + [dependencies.proc-macro2] version = "1.0.7" @@ -34,6 +39,7 @@ version = "1" [dependencies.syn] version = "1.0.56" features = ["full"] + [dev-dependencies.tokio] version = "1.0.0" features = ["full"] diff --git a/Cargo.toml.orig b/Cargo.toml.orig index d9b0579..ea536a8 100644 --- a/Cargo.toml.orig +++ b/Cargo.toml.orig @@ -3,10 +3,10 @@ name = "tokio-macros" # When releasing to crates.io: # - Remove path dependencies # - Update CHANGELOG.md. -# - Create "tokio-macros-1.0.x" git tag. -version = "1.7.0" +# - Create "tokio-macros-1.x.y" git tag. +version = "1.8.2" edition = "2018" -rust-version = "1.46" +rust-version = "1.49" authors = ["Tokio Contributors "] license = "MIT" repository = "https://github.com/tokio-rs/tokio" diff --git a/LICENSE b/LICENSE index e4f802a..a3753c0 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2021 Tokio Contributors +Copyright (c) 2022 Tokio Contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated diff --git a/METADATA b/METADATA index c40d9bc..e03bdf5 100644 --- a/METADATA +++ b/METADATA @@ -1,3 +1,7 @@ +# This project was upgraded with external_updater. +# Usage: tools/external_updater/updater.sh update rust/crates/tokio-macros +# For more info, check https://cs.android.com/android/platform/superproject/+/master:tools/external_updater/README.md + name: "tokio-macros" description: "Tokio\'s proc macros." third_party { @@ -7,13 +11,13 @@ third_party { } url { type: ARCHIVE - value: "https://static.crates.io/crates/tokio-macros/tokio-macros-1.7.0.crate" + value: "https://static.crates.io/crates/tokio-macros/tokio-macros-1.8.2.crate" } - version: "1.7.0" + version: "1.8.2" license_type: NOTICE last_upgrade_date { year: 2022 - month: 3 - day: 1 + month: 12 + day: 12 } } diff --git a/src/entry.rs b/src/entry.rs index 5cb4a49..6460e70 100644 --- a/src/entry.rs +++ b/src/entry.rs @@ -1,5 +1,5 @@ use proc_macro::TokenStream; -use proc_macro2::Span; +use proc_macro2::{Ident, Span}; use quote::{quote, quote_spanned, ToTokens}; use syn::parse::Parser; @@ -29,6 +29,7 @@ struct FinalConfig { flavor: RuntimeFlavor, worker_threads: Option, start_paused: Option, + crate_name: Option, } /// Config used in case of the attribute not being able to build a valid config @@ -36,6 +37,7 @@ const DEFAULT_ERROR_CONFIG: FinalConfig = FinalConfig { flavor: RuntimeFlavor::CurrentThread, worker_threads: None, start_paused: None, + crate_name: None, }; struct Configuration { @@ -45,6 +47,7 @@ struct Configuration { worker_threads: Option<(usize, Span)>, start_paused: Option<(bool, Span)>, is_test: bool, + crate_name: Option, } impl Configuration { @@ -59,6 +62,7 @@ impl Configuration { worker_threads: None, start_paused: None, is_test, + crate_name: None, } } @@ -104,6 +108,15 @@ impl Configuration { Ok(()) } + fn set_crate_name(&mut self, name: syn::Lit, span: Span) -> Result<(), syn::Error> { + if self.crate_name.is_some() { + return Err(syn::Error::new(span, "`crate` set multiple times.")); + } + let name_ident = parse_ident(name, span, "crate")?; + self.crate_name = Some(name_ident.to_string()); + Ok(()) + } + fn macro_name(&self) -> &'static str { if self.is_test { "tokio::test" @@ -151,6 +164,7 @@ impl Configuration { }; Ok(FinalConfig { + crate_name: self.crate_name.clone(), flavor, worker_threads, start_paused, @@ -185,6 +199,27 @@ fn parse_string(int: syn::Lit, span: Span, field: &str) -> Result Result { + match lit { + syn::Lit::Str(s) => { + let err = syn::Error::new( + span, + format!( + "Failed to parse value of `{}` as ident: \"{}\"", + field, + s.value() + ), + ); + let path = s.parse::().map_err(|_| err.clone())?; + path.get_ident().cloned().ok_or(err) + } + _ => Err(syn::Error::new( + span, + format!("Failed to parse value of `{}` as ident.", field), + )), + } +} + fn parse_bool(bool: syn::Lit, span: Span, field: &str) -> Result { match bool { syn::Lit::Bool(b) => Ok(b.value), @@ -243,9 +278,15 @@ fn build_config( let msg = "Attribute `core_threads` is renamed to `worker_threads`"; return Err(syn::Error::new_spanned(namevalue, msg)); } + "crate" => { + config.set_crate_name( + namevalue.lit.clone(), + syn::spanned::Spanned::span(&namevalue.lit), + )?; + } name => { let msg = format!( - "Unknown attribute {} is specified; expected one of: `flavor`, `worker_threads`, `start_paused`", + "Unknown attribute {} is specified; expected one of: `flavor`, `worker_threads`, `start_paused`, `crate`", name, ); return Err(syn::Error::new_spanned(namevalue, msg)); @@ -275,7 +316,7 @@ fn build_config( format!("The `{}` attribute requires an argument.", name) } name => { - format!("Unknown attribute {} is specified; expected one of: `flavor`, `worker_threads`, `start_paused`", name) + format!("Unknown attribute {} is specified; expected one of: `flavor`, `worker_threads`, `start_paused`, `crate`", name) } }; return Err(syn::Error::new_spanned(path, msg)); @@ -313,12 +354,16 @@ fn parse_knobs(mut input: syn::ItemFn, is_test: bool, config: FinalConfig) -> To (start, end) }; + let crate_name = config.crate_name.as_deref().unwrap_or("tokio"); + + let crate_ident = Ident::new(crate_name, last_stmt_start_span); + let mut rt = match config.flavor { RuntimeFlavor::CurrentThread => quote_spanned! {last_stmt_start_span=> - tokio::runtime::Builder::new_current_thread() + #crate_ident::runtime::Builder::new_current_thread() }, RuntimeFlavor::Threaded => quote_spanned! {last_stmt_start_span=> - tokio::runtime::Builder::new_multi_thread() + #crate_ident::runtime::Builder::new_multi_thread() }, }; if let Some(v) = config.worker_threads { @@ -338,29 +383,50 @@ fn parse_knobs(mut input: syn::ItemFn, is_test: bool, config: FinalConfig) -> To let body = &input.block; let brace_token = input.block.brace_token; - let (tail_return, tail_semicolon) = match body.stmts.last() { - Some(syn::Stmt::Semi(syn::Expr::Return(_), _)) => (quote! { return }, quote! { ; }), - Some(syn::Stmt::Semi(..)) | Some(syn::Stmt::Local(..)) | None => { - match &input.sig.output { - syn::ReturnType::Type(_, ty) if matches!(&**ty, syn::Type::Tuple(ty) if ty.elems.is_empty()) => - { - (quote! {}, quote! { ; }) // unit - } - syn::ReturnType::Default => (quote! {}, quote! { ; }), // unit - syn::ReturnType::Type(..) => (quote! {}, quote! {}), // ! or another - } - } - _ => (quote! {}, quote! {}), - }; - input.block = syn::parse2(quote_spanned! {last_stmt_end_span=> + let body_ident = quote! { body }; + let block_expr = quote_spanned! {last_stmt_end_span=> + #[allow(clippy::expect_used, clippy::diverging_sub_expression)] { - let body = async #body; - #[allow(clippy::expect_used)] - #tail_return #rt + return #rt .enable_all() .build() .expect("Failed building the Runtime") - .block_on(body)#tail_semicolon + .block_on(#body_ident); + } + }; + + // For test functions pin the body to the stack and use `Pin<&mut dyn + // Future>` to reduce the amount of `Runtime::block_on` (and related + // functions) copies we generate during compilation due to the generic + // parameter `F` (the future to block on). This could have an impact on + // performance, but because it's only for testing it's unlikely to be very + // large. + // + // We don't do this for the main function as it should only be used once so + // there will be no benefit. + let body = if is_test { + let output_type = match &input.sig.output { + // For functions with no return value syn doesn't print anything, + // but that doesn't work as `Output` for our boxed `Future`, so + // default to `()` (the same type as the function output). + syn::ReturnType::Default => quote! { () }, + syn::ReturnType::Type(_, ret_type) => quote! { #ret_type }, + }; + quote! { + let body = async #body; + #crate_ident::pin!(body); + let body: ::std::pin::Pin<&mut dyn ::std::future::Future> = body; + } + } else { + quote! { + let body = async #body; + } + }; + + input.block = syn::parse2(quote! { + { + #body + #block_expr } }) .expect("Parsing failure"); @@ -414,7 +480,7 @@ pub(crate) fn test(args: TokenStream, item: TokenStream, rt_multi_thread: bool) }; let config = if let Some(attr) = input.attrs.iter().find(|attr| attr.path.is_ident("test")) { let msg = "second test attribute is supplied"; - Err(syn::Error::new_spanned(&attr, msg)) + Err(syn::Error::new_spanned(attr, msg)) } else { AttributeArgs::parse_terminated .parse(args) diff --git a/src/lib.rs b/src/lib.rs index 38638a1..34041af 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -168,12 +168,32 @@ use proc_macro::TokenStream; /// /// Note that `start_paused` requires the `test-util` feature to be enabled. /// -/// ### NOTE: +/// ### Rename package /// -/// If you rename the Tokio crate in your dependencies this macro will not work. -/// If you must rename the current version of Tokio because you're also using an -/// older version of Tokio, you _must_ make the current version of Tokio -/// available as `tokio` in the module where this macro is expanded. +/// ```rust +/// use tokio as tokio1; +/// +/// #[tokio1::main(crate = "tokio1")] +/// async fn main() { +/// println!("Hello world"); +/// } +/// ``` +/// +/// Equivalent code not using `#[tokio::main]` +/// +/// ```rust +/// use tokio as tokio1; +/// +/// fn main() { +/// tokio1::runtime::Builder::new_multi_thread() +/// .enable_all() +/// .build() +/// .unwrap() +/// .block_on(async { +/// println!("Hello world"); +/// }) +/// } +/// ``` #[proc_macro_attribute] #[cfg(not(test))] // Work around for rust-lang/rust#62127 pub fn main(args: TokenStream, item: TokenStream) -> TokenStream { @@ -213,23 +233,52 @@ pub fn main(args: TokenStream, item: TokenStream) -> TokenStream { /// } /// ``` /// -/// ### NOTE: +/// ### Rename package +/// +/// ```rust +/// use tokio as tokio1; +/// +/// #[tokio1::main(crate = "tokio1")] +/// async fn main() { +/// println!("Hello world"); +/// } +/// ``` /// -/// If you rename the Tokio crate in your dependencies this macro will not work. -/// If you must rename the current version of Tokio because you're also using an -/// older version of Tokio, you _must_ make the current version of Tokio -/// available as `tokio` in the module where this macro is expanded. +/// Equivalent code not using `#[tokio::main]` +/// +/// ```rust +/// use tokio as tokio1; +/// +/// fn main() { +/// tokio1::runtime::Builder::new_multi_thread() +/// .enable_all() +/// .build() +/// .unwrap() +/// .block_on(async { +/// println!("Hello world"); +/// }) +/// } +/// ``` #[proc_macro_attribute] #[cfg(not(test))] // Work around for rust-lang/rust#62127 pub fn main_rt(args: TokenStream, item: TokenStream) -> TokenStream { entry::main(args, item, false) } -/// Marks async function to be executed by runtime, suitable to test environment +/// Marks async function to be executed by runtime, suitable to test environment. +/// This macro helps set up a `Runtime` without requiring the user to use +/// [Runtime](../tokio/runtime/struct.Runtime.html) or +/// [Builder](../tokio/runtime/struct.Builder.html) directly. /// -/// ## Usage +/// Note: This macro is designed to be simplistic and targets applications that +/// do not require a complex setup. If the provided functionality is not +/// sufficient, you may be interested in using +/// [Builder](../tokio/runtime/struct.Builder.html), which provides a more +/// powerful interface. /// -/// ### Multi-thread runtime +/// # Multi-threaded runtime +/// +/// To use the multi-threaded runtime, the macro can be configured using /// /// ```no_run /// #[tokio::test(flavor = "multi_thread", worker_threads = 1)] @@ -238,9 +287,52 @@ pub fn main_rt(args: TokenStream, item: TokenStream) -> TokenStream { /// } /// ``` /// -/// ### Using default +/// The `worker_threads` option configures the number of worker threads, and +/// defaults to the number of cpus on the system. This is the default +/// flavor. +/// +/// Note: The multi-threaded runtime requires the `rt-multi-thread` feature +/// flag. +/// +/// # Current thread runtime +/// +/// The default test runtime is single-threaded. Each test gets a +/// separate current-thread runtime. +/// +/// ```no_run +/// #[tokio::test] +/// async fn my_test() { +/// assert!(true); +/// } +/// ``` +/// +/// ## Usage +/// +/// ### Using the multi-thread runtime /// -/// The default test runtime is single-threaded. +/// ```no_run +/// #[tokio::test(flavor = "multi_thread")] +/// async fn my_test() { +/// assert!(true); +/// } +/// ``` +/// +/// Equivalent code not using `#[tokio::test]` +/// +/// ```no_run +/// #[test] +/// fn my_test() { +/// tokio::runtime::Builder::new_multi_thread() +/// .enable_all() +/// .build() +/// .unwrap() +/// .block_on(async { +/// assert!(true); +/// }) +/// } +/// ``` +/// +/// ### Using current thread runtime /// /// ```no_run /// #[tokio::test] @@ -249,6 +341,46 @@ pub fn main_rt(args: TokenStream, item: TokenStream) -> TokenStream { /// } /// ``` /// +/// Equivalent code not using `#[tokio::test]` +/// +/// ```no_run +/// #[test] +/// fn my_test() { +/// tokio::runtime::Builder::new_current_thread() +/// .enable_all() +/// .build() +/// .unwrap() +/// .block_on(async { +/// assert!(true); +/// }) +/// } +/// ``` +/// +/// ### Set number of worker threads +/// +/// ```no_run +/// #[tokio::test(flavor ="multi_thread", worker_threads = 2)] +/// async fn my_test() { +/// assert!(true); +/// } +/// ``` +/// +/// Equivalent code not using `#[tokio::test]` +/// +/// ```no_run +/// #[test] +/// fn my_test() { +/// tokio::runtime::Builder::new_multi_thread() +/// .worker_threads(2) +/// .enable_all() +/// .build() +/// .unwrap() +/// .block_on(async { +/// assert!(true); +/// }) +/// } +/// ``` +/// /// ### Configure the runtime to start with time paused /// /// ```no_run @@ -258,14 +390,34 @@ pub fn main_rt(args: TokenStream, item: TokenStream) -> TokenStream { /// } /// ``` /// +/// Equivalent code not using `#[tokio::test]` +/// +/// ```no_run +/// #[test] +/// fn my_test() { +/// tokio::runtime::Builder::new_current_thread() +/// .enable_all() +/// .start_paused(true) +/// .build() +/// .unwrap() +/// .block_on(async { +/// assert!(true); +/// }) +/// } +/// ``` +/// /// Note that `start_paused` requires the `test-util` feature to be enabled. /// -/// ### NOTE: +/// ### Rename package /// -/// If you rename the Tokio crate in your dependencies this macro will not work. -/// If you must rename the current version of Tokio because you're also using an -/// older version of Tokio, you _must_ make the current version of Tokio -/// available as `tokio` in the module where this macro is expanded. +/// ```rust +/// use tokio as tokio1; +/// +/// #[tokio1::test(crate = "tokio1")] +/// async fn my_test() { +/// println!("Hello world"); +/// } +/// ``` #[proc_macro_attribute] pub fn test(args: TokenStream, item: TokenStream) -> TokenStream { entry::test(args, item, true) @@ -281,13 +433,6 @@ pub fn test(args: TokenStream, item: TokenStream) -> TokenStream { /// assert!(true); /// } /// ``` -/// -/// ### NOTE: -/// -/// If you rename the Tokio crate in your dependencies this macro will not work. -/// If you must rename the current version of Tokio because you're also using an -/// older version of Tokio, you _must_ make the current version of Tokio -/// available as `tokio` in the module where this macro is expanded. #[proc_macro_attribute] pub fn test_rt(args: TokenStream, item: TokenStream) -> TokenStream { entry::test(args, item, false) -- cgit v1.2.3