Snap for 8358640 from a2e0086b1a3443173b9d9951ca9b11a3a6ca3d83 to mainline-go-extservices-release

Change-Id: Ide7ceba5366c0b69daf15fa0cb038d16122f7856
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index f3ad3ab..942329b 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,6 @@
 {
   "git": {
-    "sha1": "c91f8691672c7401b1923ab00bf138975c99391a"
-  }
-}
+    "sha1": "fc1e3250219170e31cddb8857a276cba7dd08d44"
+  },
+  "path_in_vcs": "futures-macro"
+}
\ No newline at end of file
diff --git a/Android.bp b/Android.bp
index 996d4d9..7674084 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,4 +1,4 @@
-// This file is generated by cargo2android.py --run --dependencies.
+// This file is generated by cargo2android.py --config cargo2android.json.
 // Do not modify this file as changes will be overridden on upgrade.
 
 package {
@@ -40,6 +40,8 @@
 rust_proc_macro {
     name: "libfutures_macro",
     crate_name: "futures_macro",
+    cargo_env_compat: true,
+    cargo_pkg_version: "0.3.21",
     srcs: ["src/lib.rs"],
     edition: "2018",
     rustlibs: [
@@ -47,12 +49,4 @@
         "libquote",
         "libsyn",
     ],
-    proc_macros: ["libproc_macro_hack"],
 }
-
-// dependent_library ["feature_list"]
-//   proc-macro-hack-0.5.19
-//   proc-macro2-1.0.26 "default,proc-macro"
-//   quote-1.0.9 "default,proc-macro"
-//   syn-1.0.68 "clone-impls,default,derive,full,parsing,printing,proc-macro,quote"
-//   unicode-xid-0.2.1 "default"
diff --git a/Cargo.toml b/Cargo.toml
index a01c8cc..86fc5c9 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -3,28 +3,26 @@
 # When uploading crates to the registry Cargo will automatically
 # "normalize" Cargo.toml files for maximal compatibility
 # with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies
+# to registry (e.g., crates.io) dependencies.
 #
-# If you believe there's an error in this file please file an
-# issue against the rust-lang/cargo repository. If you're
-# editing this file be aware that the upstream Cargo.toml
-# will likely look very different (and much more reasonable)
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
 
 [package]
 edition = "2018"
+rust-version = "1.45"
 name = "futures-macro"
-version = "0.3.13"
-authors = ["Taylor Cramer <[email protected]>", "Taiki Endo <[email protected]>"]
-description = "The futures-rs procedural macro implementations.\n"
+version = "0.3.21"
+description = """
+The futures-rs procedural macro implementations.
+"""
 homepage = "https://rust-lang.github.io/futures-rs"
-documentation = "https://docs.rs/futures-macro/0.3"
 license = "MIT OR Apache-2.0"
 repository = "https://github.com/rust-lang/futures-rs"
 
 [lib]
 proc-macro = true
-[dependencies.proc-macro-hack]
-version = "0.5.19"
 
 [dependencies.proc-macro2]
 version = "1.0"
@@ -33,7 +31,7 @@
 version = "1.0"
 
 [dependencies.syn]
-version = "1.0"
+version = "1.0.56"
 features = ["full"]
 
 [features]
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index 090f736..a929d0f 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,12 +1,11 @@
 [package]
 name = "futures-macro"
+version = "0.3.21"
 edition = "2018"
-version = "0.3.13"
-authors = ["Taylor Cramer <[email protected]>", "Taiki Endo <[email protected]>"]
+rust-version = "1.45"
 license = "MIT OR Apache-2.0"
 repository = "https://github.com/rust-lang/futures-rs"
 homepage = "https://rust-lang.github.io/futures-rs"
-documentation = "https://docs.rs/futures-macro/0.3"
 description = """
 The futures-rs procedural macro implementations.
 """
@@ -18,6 +17,5 @@
 
 [dependencies]
 proc-macro2 = "1.0"
-proc-macro-hack = "0.5.19"
 quote = "1.0"
-syn = { version = "1.0", features = ["full"] }
+syn = { version = "1.0.56", features = ["full"] }
diff --git a/METADATA b/METADATA
index 05b2aa8..ca144da 100644
--- a/METADATA
+++ b/METADATA
@@ -7,13 +7,13 @@
   }
   url {
     type: ARCHIVE
-    value: "https://static.crates.io/crates/futures-macro/futures-macro-0.3.13.crate"
+    value: "https://static.crates.io/crates/futures-macro/futures-macro-0.3.21.crate"
   }
-  version: "0.3.13"
+  version: "0.3.21"
   license_type: NOTICE
   last_upgrade_date {
-    year: 2021
-    month: 4
+    year: 2022
+    month: 3
     day: 1
   }
 }
diff --git a/TEST_MAPPING b/TEST_MAPPING
index a86ecdd..5ef61de 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -1,56 +1,45 @@
 // Generated by update_crate_tests.py for tests that depend on this crate.
 {
+  "imports": [
+    {
+      "path": "external/rust/crates/anyhow"
+    },
+    {
+      "path": "external/rust/crates/futures-util"
+    },
+    {
+      "path": "external/rust/crates/tokio"
+    },
+    {
+      "path": "external/rust/crates/tokio-test"
+    }
+  ],
   "presubmit": [
     {
-      "name": "tokio-test_device_test_src_lib"
+      "name": "ZipFuseTest"
     },
     {
-      "name": "tokio-test_device_test_tests_io"
+      "name": "authfs_device_test_src_lib"
     },
     {
-      "name": "tokio-test_device_test_tests_macros"
+      "name": "doh_unit_test"
     },
     {
-      "name": "anyhow_device_test_tests_test_convert"
+      "name": "virtualizationservice_device_test"
+    }
+  ],
+  "presubmit-rust": [
+    {
+      "name": "ZipFuseTest"
     },
     {
-      "name": "tokio-test_device_test_tests_block_on"
+      "name": "authfs_device_test_src_lib"
     },
     {
-      "name": "anyhow_device_test_tests_test_source"
+      "name": "doh_unit_test"
     },
     {
-      "name": "anyhow_device_test_tests_test_context"
-    },
-    {
-      "name": "anyhow_device_test_tests_test_fmt"
-    },
-    {
-      "name": "anyhow_device_test_tests_test_macros"
-    },
-    {
-      "name": "anyhow_device_test_tests_test_repr"
-    },
-    {
-      "name": "futures-util_device_test_src_lib"
-    },
-    {
-      "name": "anyhow_device_test_tests_test_ffi"
-    },
-    {
-      "name": "anyhow_device_test_tests_test_chain"
-    },
-    {
-      "name": "anyhow_device_test_tests_test_boxed"
-    },
-    {
-      "name": "anyhow_device_test_tests_test_autotrait"
-    },
-    {
-      "name": "anyhow_device_test_src_lib"
-    },
-    {
-      "name": "anyhow_device_test_tests_test_downcast"
+      "name": "virtualizationservice_device_test"
     }
   ]
 }
diff --git a/cargo2android.json b/cargo2android.json
new file mode 100644
index 0000000..958632b
--- /dev/null
+++ b/cargo2android.json
@@ -0,0 +1,3 @@
+{
+  "run": true
+}
\ No newline at end of file
diff --git a/src/executor.rs b/src/executor.rs
new file mode 100644
index 0000000..40a091f
--- /dev/null
+++ b/src/executor.rs
@@ -0,0 +1,55 @@
+use proc_macro::TokenStream;
+use proc_macro2::Span;
+use quote::{quote, quote_spanned, ToTokens};
+
+pub(crate) fn test(args: TokenStream, item: TokenStream) -> TokenStream {
+    if !args.is_empty() {
+        return syn::Error::new_spanned(proc_macro2::TokenStream::from(args), "invalid argument")
+            .to_compile_error()
+            .into();
+    }
+
+    let mut input = syn::parse_macro_input!(item as syn::ItemFn);
+
+    if input.sig.asyncness.take().is_none() {
+        return syn::Error::new_spanned(input.sig.fn_token, "Only async functions are supported")
+            .to_compile_error()
+            .into();
+    }
+
+    // If type mismatch occurs, the current rustc points to the last statement.
+    let (last_stmt_start_span, last_stmt_end_span) = {
+        let mut last_stmt = input
+            .block
+            .stmts
+            .last()
+            .map(ToTokens::into_token_stream)
+            .unwrap_or_default()
+            .into_iter();
+        // `Span` on stable Rust has a limitation that only points to the first
+        // token, not the whole tokens. We can work around this limitation by
+        // using the first/last span of the tokens like
+        // `syn::Error::new_spanned` does.
+        let start = last_stmt.next().map_or_else(Span::call_site, |t| t.span());
+        let end = last_stmt.last().map_or(start, |t| t.span());
+        (start, end)
+    };
+
+    let path = quote_spanned! {last_stmt_start_span=>
+        ::futures_test::__private
+    };
+    let body = &input.block;
+    input.block.stmts = vec![syn::Stmt::Expr(
+        syn::parse2(quote_spanned! {last_stmt_end_span=>
+            #path::block_on(async #body)
+        })
+        .unwrap(),
+    )];
+
+    let gen = quote! {
+        #[::core::prelude::v1::test]
+        #input
+    };
+
+    gen.into()
+}
diff --git a/src/join.rs b/src/join.rs
index 048b62a..d427da2 100644
--- a/src/join.rs
+++ b/src/join.rs
@@ -27,10 +27,7 @@
     }
 }
 
-fn bind_futures(
-    fut_exprs: Vec<Expr>,
-    span: Span,
-) -> (Vec<TokenStream2>, Vec<Ident>) {
+fn bind_futures(fut_exprs: Vec<Expr>, span: Span) -> (Vec<TokenStream2>, Vec<Ident>) {
     let mut future_let_bindings = Vec::with_capacity(fut_exprs.len());
     let future_names: Vec<_> = fut_exprs
         .into_iter()
diff --git a/src/lib.rs b/src/lib.rs
index 5f0c47c..0afe34b 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,11 +1,13 @@
 //! The futures-rs procedural macro implementations.
 
-#![recursion_limit = "128"]
-#![warn(rust_2018_idioms, unreachable_pub)]
-// It cannot be included in the published code because this lints have false positives in the minimum required version.
-#![cfg_attr(test, warn(single_use_lifetimes))]
-#![warn(clippy::all)]
-#![doc(test(attr(deny(warnings), allow(dead_code, unused_assignments, unused_variables))))]
+#![warn(rust_2018_idioms, single_use_lifetimes, unreachable_pub)]
+#![doc(test(
+    no_crate_inject,
+    attr(
+        deny(warnings, rust_2018_idioms, single_use_lifetimes),
+        allow(dead_code, unused_assignments, unused_variables)
+    )
+))]
 
 // Since https://github.com/rust-lang/cargo/pull/7700 `proc_macro` is part of the prelude for
 // proc-macro crates, but to support older compilers we still need this explicit `extern crate`.
@@ -13,31 +15,47 @@
 extern crate proc_macro;
 
 use proc_macro::TokenStream;
-use proc_macro_hack::proc_macro_hack;
 
+mod executor;
 mod join;
 mod select;
+mod stream_select;
 
 /// The `join!` macro.
-#[proc_macro_hack]
+#[proc_macro]
 pub fn join_internal(input: TokenStream) -> TokenStream {
     crate::join::join(input)
 }
 
 /// The `try_join!` macro.
-#[proc_macro_hack]
+#[proc_macro]
 pub fn try_join_internal(input: TokenStream) -> TokenStream {
     crate::join::try_join(input)
 }
 
 /// The `select!` macro.
-#[proc_macro_hack]
+#[proc_macro]
 pub fn select_internal(input: TokenStream) -> TokenStream {
     crate::select::select(input)
 }
 
 /// The `select_biased!` macro.
-#[proc_macro_hack]
+#[proc_macro]
 pub fn select_biased_internal(input: TokenStream) -> TokenStream {
     crate::select::select_biased(input)
 }
+
+// TODO: Change this to doc comment once rustdoc bug fixed: https://github.com/rust-lang/futures-rs/pull/2435
+// The `test` attribute.
+#[proc_macro_attribute]
+pub fn test_internal(input: TokenStream, item: TokenStream) -> TokenStream {
+    crate::executor::test(input, item)
+}
+
+/// The `stream_select!` macro.
+#[proc_macro]
+pub fn stream_select_internal(input: TokenStream) -> TokenStream {
+    crate::stream_select::stream_select(input.into())
+        .unwrap_or_else(syn::Error::into_compile_error)
+        .into()
+}
diff --git a/src/select.rs b/src/select.rs
index 65b3187..0c8e5f1 100644
--- a/src/select.rs
+++ b/src/select.rs
@@ -3,8 +3,8 @@
 use proc_macro::TokenStream;
 use proc_macro2::Span;
 use quote::{format_ident, quote};
-use syn::{parse_quote, Expr, Ident, Pat, Token};
 use syn::parse::{Parse, ParseStream};
+use syn::{parse_quote, Expr, Ident, Pat, Token};
 
 mod kw {
     syn::custom_keyword!(complete);
@@ -63,7 +63,10 @@
 
             // Commas after the expression are only optional if it's a `Block`
             // or it is the last branch in the `match`.
-            let is_block = match expr { Expr::Block(_) => true, _ => false };
+            let is_block = match expr {
+                Expr::Block(_) => true,
+                _ => false,
+            };
             if is_block || input.is_empty() {
                 input.parse::<Option<Token![,]>>()?;
             } else {
@@ -76,7 +79,7 @@
                 CaseKind::Normal(pat, fut_expr) => {
                     select.normal_fut_exprs.push(fut_expr);
                     select.normal_fut_handlers.push((pat, expr));
-                },
+                }
             }
         }
 
@@ -92,22 +95,16 @@
     result_ident: Ident,
     variants: usize,
     complete: bool,
-    span: Span
+    span: Span,
 ) -> (Vec<Ident>, syn::ItemEnum) {
     // "_0", "_1", "_2"
     let variant_names: Vec<Ident> =
-        (0..variants)
-            .map(|num| format_ident!("_{}", num, span = span))
-            .collect();
+        (0..variants).map(|num| format_ident!("_{}", num, span = span)).collect();
 
     let type_parameters = &variant_names;
     let variants = &variant_names;
 
-    let complete_variant = if complete {
-        Some(quote!(Complete))
-    } else {
-        None
-    };
+    let complete_variant = if complete { Some(quote!(Complete)) } else { None };
 
     let enum_item = parse_quote! {
         enum #result_ident<#(#type_parameters,)*> {
@@ -148,7 +145,9 @@
 
     // bind non-`Ident` future exprs w/ `let`
     let mut future_let_bindings = Vec::with_capacity(parsed.normal_fut_exprs.len());
-    let bound_future_names: Vec<_> = parsed.normal_fut_exprs.into_iter()
+    let bound_future_names: Vec<_> = parsed
+        .normal_fut_exprs
+        .into_iter()
         .zip(variant_names.iter())
         .map(|(expr, variant_name)| {
             match expr {
@@ -164,7 +163,7 @@
                         __futures_crate::async_await::assert_unpin(&#path);
                     });
                     path
-                },
+                }
                 _ => {
                     // Bind and pin the resulting Future on the stack. This is
                     // necessary to support direct select! calls on !Unpin
@@ -188,8 +187,8 @@
 
     // For each future, make an `&mut dyn FnMut(&mut Context<'_>) -> Option<Poll<__PrivResult<...>>`
     // to use for polling that individual future. These will then be put in an array.
-    let poll_functions = bound_future_names.iter().zip(variant_names.iter())
-        .map(|(bound_future_name, variant_name)| {
+    let poll_functions = bound_future_names.iter().zip(variant_names.iter()).map(
+        |(bound_future_name, variant_name)| {
             // Below we lazily create the Pin on the Future below.
             // This is done in order to avoid allocating memory in the generator
             // for the Pin variable.
@@ -216,7 +215,8 @@
                     &mut __futures_crate::task::Context<'_>
                 ) -> __futures_crate::Option<__futures_crate::task::Poll<_>> = &mut #variant_name;
             }
-        });
+        },
+    );
 
     let none_polled = if parsed.complete.is_some() {
         quote! {
@@ -229,13 +229,13 @@
         }
     };
 
-    let branches = parsed.normal_fut_handlers.into_iter()
-        .zip(variant_names.iter())
-        .map(|((pat, expr), variant_name)| {
+    let branches = parsed.normal_fut_handlers.into_iter().zip(variant_names.iter()).map(
+        |((pat, expr), variant_name)| {
             quote! {
                 #enum_ident::#variant_name(#pat) => { #expr },
             }
-        });
+        },
+    );
     let branches = quote! { #( #branches )* };
 
     let complete_branch = parsed.complete.map(|complete_expr| {
diff --git a/src/stream_select.rs b/src/stream_select.rs
new file mode 100644
index 0000000..9927b53
--- /dev/null
+++ b/src/stream_select.rs
@@ -0,0 +1,113 @@
+use proc_macro2::TokenStream;
+use quote::{format_ident, quote, ToTokens};
+use syn::{parse::Parser, punctuated::Punctuated, Expr, Index, Token};
+
+/// The `stream_select!` macro.
+pub(crate) fn stream_select(input: TokenStream) -> Result<TokenStream, syn::Error> {
+    let args = Punctuated::<Expr, Token![,]>::parse_terminated.parse2(input)?;
+    if args.len() < 2 {
+        return Ok(quote! {
+           compile_error!("stream select macro needs at least two arguments.")
+        });
+    }
+    let generic_idents = (0..args.len()).map(|i| format_ident!("_{}", i)).collect::<Vec<_>>();
+    let field_idents = (0..args.len()).map(|i| format_ident!("__{}", i)).collect::<Vec<_>>();
+    let field_idents_2 = (0..args.len()).map(|i| format_ident!("___{}", i)).collect::<Vec<_>>();
+    let field_indices = (0..args.len()).map(Index::from).collect::<Vec<_>>();
+    let args = args.iter().map(|e| e.to_token_stream());
+
+    Ok(quote! {
+        {
+            #[derive(Debug)]
+            struct StreamSelect<#(#generic_idents),*> (#(Option<#generic_idents>),*);
+
+            enum StreamEnum<#(#generic_idents),*> {
+                #(
+                    #generic_idents(#generic_idents)
+                ),*,
+                None,
+            }
+
+            impl<ITEM, #(#generic_idents),*> __futures_crate::stream::Stream for StreamEnum<#(#generic_idents),*>
+            where #(#generic_idents: __futures_crate::stream::Stream<Item=ITEM> + ::std::marker::Unpin,)*
+            {
+                type Item = ITEM;
+
+                fn poll_next(mut self: ::std::pin::Pin<&mut Self>, cx: &mut __futures_crate::task::Context<'_>) -> __futures_crate::task::Poll<Option<Self::Item>> {
+                    match self.get_mut() {
+                        #(
+                            Self::#generic_idents(#generic_idents) => ::std::pin::Pin::new(#generic_idents).poll_next(cx)
+                        ),*,
+                        Self::None => panic!("StreamEnum::None should never be polled!"),
+                    }
+                }
+            }
+
+            impl<ITEM, #(#generic_idents),*> __futures_crate::stream::Stream for StreamSelect<#(#generic_idents),*>
+            where #(#generic_idents: __futures_crate::stream::Stream<Item=ITEM> + ::std::marker::Unpin,)*
+            {
+                type Item = ITEM;
+
+                fn poll_next(mut self: ::std::pin::Pin<&mut Self>, cx: &mut __futures_crate::task::Context<'_>) -> __futures_crate::task::Poll<Option<Self::Item>> {
+                    let Self(#(ref mut #field_idents),*) = self.get_mut();
+                    #(
+                        let mut #field_idents_2 = false;
+                    )*
+                    let mut any_pending = false;
+                    {
+                        let mut stream_array = [#(#field_idents.as_mut().map(|f| StreamEnum::#generic_idents(f)).unwrap_or(StreamEnum::None)),*];
+                        __futures_crate::async_await::shuffle(&mut stream_array);
+
+                        for mut s in stream_array {
+                            if let StreamEnum::None = s {
+                                continue;
+                            } else {
+                                match __futures_crate::stream::Stream::poll_next(::std::pin::Pin::new(&mut s), cx) {
+                                    r @ __futures_crate::task::Poll::Ready(Some(_)) => {
+                                        return r;
+                                    },
+                                    __futures_crate::task::Poll::Pending => {
+                                        any_pending = true;
+                                    },
+                                    __futures_crate::task::Poll::Ready(None) => {
+                                        match s {
+                                            #(
+                                                StreamEnum::#generic_idents(_) => { #field_idents_2 = true; }
+                                            ),*,
+                                            StreamEnum::None => panic!("StreamEnum::None should never be polled!"),
+                                        }
+                                    },
+                                }
+                            }
+                        }
+                    }
+                    #(
+                        if #field_idents_2 {
+                            *#field_idents = None;
+                        }
+                    )*
+                    if any_pending {
+                        __futures_crate::task::Poll::Pending
+                    } else {
+                        __futures_crate::task::Poll::Ready(None)
+                    }
+                }
+
+                fn size_hint(&self) -> (usize, Option<usize>) {
+                    let mut s = (0, Some(0));
+                    #(
+                        if let Some(new_hint) = self.#field_indices.as_ref().map(|s| s.size_hint()) {
+                            s.0 += new_hint.0;
+                            // We can change this out for `.zip` when the MSRV is 1.46.0 or higher.
+                            s.1 = s.1.and_then(|a| new_hint.1.map(|b| a + b));
+                        }
+                    )*
+                    s
+                }
+            }
+
+            StreamSelect(#(Some(#args)),*)
+
+        }
+    })
+}