Snap for 10453563 from 6b3a6914c5e8a08bda8c1a24cd4366be7432a0d4 to mainline-adservices-release

Change-Id: I9376145968934f52b00be90eae87cb1ab8bb58f8
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index b737620..161d06e 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,6 @@
 {
   "git": {
-    "sha1": "01e2e42ef0d833682c27b0f40a2cc748d86b2dc3"
-  }
-}
+    "sha1": "0fac3ac6642dd017a36268c4cdba2f04ec050d11"
+  },
+  "path_in_vcs": ""
+}
\ No newline at end of file
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 97fcf98..f82f7f1 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -33,6 +33,7 @@
           - 1.36.0  # Oldest supported with MaybeUninit
           - 1.40.0  # Oldest supported with cfg(doctest)
           - 1.51.0  # Oldest supported with ptr::addr_of!
+          - 1.65.0  # Oldest supported with stable const evaluation (sans cell)
           - stable
           - beta
           - nightly
@@ -67,8 +68,15 @@
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v2
+      - name: Install Miri
+        run: |
+          rustup toolchain install nightly --component miri
+          rustup override set nightly
+          cargo miri setup
       - name: Test with Miri
-        run: ci/miri.sh
+        run: |
+          cargo miri test
+          cargo miri test --all-features
 
   style:
     name: lints and formatting
diff --git a/Android.bp b/Android.bp
index c8a26b5..4bcf796 100644
--- a/Android.bp
+++ b/Android.bp
@@ -23,7 +23,7 @@
     host_supported: true,
     crate_name: "memoffset",
     cargo_env_compat: true,
-    cargo_pkg_version: "0.6.5",
+    cargo_pkg_version: "0.8.0",
     srcs: ["src/lib.rs"],
     edition: "2015",
     features: ["default"],
@@ -32,14 +32,16 @@
         "doctests",
         "maybe_uninit",
         "raw_ref_macros",
+        "stable_const",
         "tuple_ty",
     ],
     apex_available: [
         "//apex_available:platform",
-        "com.android.bluetooth",
+        "com.android.btservices",
         "com.android.compos",
         "com.android.virt",
     ],
+    product_available: true,
     vendor_available: true,
     min_sdk_version: "29",
 }
@@ -49,7 +51,7 @@
     host_supported: true,
     crate_name: "memoffset",
     cargo_env_compat: true,
-    cargo_pkg_version: "0.6.5",
+    cargo_pkg_version: "0.8.0",
     srcs: ["src/lib.rs"],
     test_suites: ["general-tests"],
     auto_gen_config: true,
@@ -63,6 +65,7 @@
         "doctests",
         "maybe_uninit",
         "raw_ref_macros",
+        "stable_const",
         "tuple_ty",
     ],
 }
diff --git a/Cargo.toml b/Cargo.toml
index 2874e31..5d71c64 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -11,16 +11,23 @@
 
 [package]
 name = "memoffset"
-version = "0.6.5"
+version = "0.8.0"
 authors = ["Gilad Naaman <gilad.naaman@gmail.com>"]
 description = "offset_of functionality for Rust structs."
 readme = "README.md"
-keywords = ["mem", "offset", "offset_of", "offsetof"]
+keywords = [
+    "mem",
+    "offset",
+    "offset_of",
+    "offsetof",
+]
 categories = ["no-std"]
 license = "MIT"
 repository = "https://github.com/Gilnaa/memoffset"
+
 [dev-dependencies.doc-comment]
 version = "0.3"
+
 [build-dependencies.autocfg]
 version = "1"
 
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index 7a62858..71bdc9e 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,6 +1,6 @@
 [package]
 name = "memoffset"
-version = "0.6.5"
+version = "0.8.0"
 authors = ["Gilad Naaman <gilad.naaman@gmail.com>"]
 description = "offset_of functionality for Rust structs."
 license = "MIT"
diff --git a/METADATA b/METADATA
index 7b4d9f1..5ccdb78 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/memoffset
+# For more info, check https://cs.android.com/android/platform/superproject/+/master:tools/external_updater/README.md
+
 name: "memoffset"
 description: "offset_of functionality for Rust structs."
 third_party {
@@ -7,13 +11,13 @@
   }
   url {
     type: ARCHIVE
-    value: "https://static.crates.io/crates/memoffset/memoffset-0.6.5.crate"
+    value: "https://static.crates.io/crates/memoffset/memoffset-0.8.0.crate"
   }
-  version: "0.6.5"
+  version: "0.8.0"
   license_type: NOTICE
   last_upgrade_date {
-    year: 2022
-    month: 3
-    day: 1
+    year: 2023
+    month: 2
+    day: 3
   }
 }
diff --git a/README.md b/README.md
index 9e93c2b..b0bfd10 100644
--- a/README.md
+++ b/README.md
@@ -7,6 +7,7 @@
 Introduces the following macros:
  * `offset_of!` for obtaining the offset of a member of a struct.
  * `offset_of_tuple!` for obtaining the offset of a member of a tuple. (Requires Rust 1.20+)
+ * `offset_of_union!` for obtaining the offset of a member of a union.
  * `span_of!` for obtaining the range that a field, or fields, span.
 
 `memoffset` works under `no_std` environments.
@@ -16,7 +17,7 @@
 
 ```toml
 [dependencies]
-memoffset = "0.6"
+memoffset = "0.8"
 ```
 
 These versions will compile fine with rustc versions greater or equal to 1.19.
@@ -45,21 +46,40 @@
 }
 ```
 
-## Feature flags ##
+## Usage in constants ##
+`memoffset` has support for compile-time `offset_of!` on rust>=1.65, or on older nightly compilers.
 
-### Usage in constants ###
-`memoffset` has **experimental** support for compile-time `offset_of!` on a nightly compiler.
+### Usage on stable Rust ###
+Constant evaluation is automatically enabled and avilable on stable compilers starting with rustc 1.65.
 
-In order to use it, you must enable the `unstable_const` crate feature and several compiler features.
+This is an incomplete implementation with one caveat:
+Due to dependence on [`#![feature(const_refs_to_cell)]`](https://github.com/rust-lang/rust/issues/80384), you cannot get the offset of a `Cell` field in a const-context.
+
+This means that if need to get the offset of a cell, you'll have to remain on nightly for now.
+
+### Usage on recent nightlies ###
+
+If you're using a new-enough nightly and you require the ability to get the offset of a `Cell`,
+you'll have to enable the `unstable_const` cargo feature, as well as enabling `const_refs_to_cell` in your crate root.
+
+Do note that `unstable_const` is an unstable feature that is set to be removed in a future version of `memoffset`.
 
 Cargo.toml:
 ```toml
 [dependencies.memoffset]
-version = "0.6"
+version = "0.8"
 features = ["unstable_const"]
 ```
 
 Your crate root: (`lib.rs`/`main.rs`)
 ```rust,ignore
+#![feature(const_refs_to_cell)]
+```
+
+### Usage on older nightlies ###
+In order to use it on an older nightly compiler, you must enable the `unstable_const` crate feature and several compiler features.
+
+Your crate root: (`lib.rs`/`main.rs`)
+```rust,ignore
 #![feature(const_ptr_offset_from, const_refs_to_cell)]
 ```
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 83479e2..448ea8a 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -11,6 +11,9 @@
       "path": "external/rust/crates/crossbeam-epoch"
     },
     {
+      "path": "external/rust/crates/hashbrown"
+    },
+    {
       "path": "external/rust/crates/tinytemplate"
     },
     {
@@ -21,106 +24,55 @@
     },
     {
       "path": "external/rust/crates/unicode-xid"
+    },
+    {
+      "path": "packages/modules/Virtualization/apkdmverity"
+    },
+    {
+      "path": "packages/modules/Virtualization/authfs"
+    },
+    {
+      "path": "packages/modules/Virtualization/encryptedstore"
+    },
+    {
+      "path": "packages/modules/Virtualization/libs/capabilities"
+    },
+    {
+      "path": "packages/modules/Virtualization/libs/devicemapper"
+    },
+    {
+      "path": "packages/modules/Virtualization/microdroid_manager"
+    },
+    {
+      "path": "packages/modules/Virtualization/virtualizationmanager"
+    },
+    {
+      "path": "packages/modules/Virtualization/vm"
+    },
+    {
+      "path": "packages/modules/Virtualization/zipfuse"
+    },
+    {
+      "path": "system/security/diced"
+    },
+    {
+      "path": "system/security/keystore2"
+    },
+    {
+      "path": "system/security/keystore2/legacykeystore"
+    },
+    {
+      "path": "system/security/keystore2/src/crypto"
     }
   ],
   "presubmit": [
     {
-      "name": "ZipFuseTest"
-    },
-    {
-      "name": "apkdmverity.test"
-    },
-    {
-      "name": "authfs_device_test_src_lib"
-    },
-    {
-      "name": "diced_open_dice_cbor_test"
-    },
-    {
-      "name": "diced_sample_inputs_test"
-    },
-    {
-      "name": "diced_test"
-    },
-    {
-      "name": "diced_utils_test"
-    },
-    {
-      "name": "diced_vendor_test"
-    },
-    {
-      "name": "keystore2_crypto_test_rust"
-    },
-    {
-      "name": "keystore2_selinux_concurrency_test"
-    },
-    {
-      "name": "keystore2_test"
-    },
-    {
-      "name": "keystore2_test_utils_test"
-    },
-    {
-      "name": "legacykeystore_test"
-    },
-    {
       "name": "memoffset_test_src_lib"
-    },
-    {
-      "name": "microdroid_manager_test"
-    },
-    {
-      "name": "virtualizationservice_device_test"
     }
   ],
   "presubmit-rust": [
     {
-      "name": "ZipFuseTest"
-    },
-    {
-      "name": "apkdmverity.test"
-    },
-    {
-      "name": "authfs_device_test_src_lib"
-    },
-    {
-      "name": "diced_open_dice_cbor_test"
-    },
-    {
-      "name": "diced_sample_inputs_test"
-    },
-    {
-      "name": "diced_test"
-    },
-    {
-      "name": "diced_utils_test"
-    },
-    {
-      "name": "diced_vendor_test"
-    },
-    {
-      "name": "keystore2_crypto_test_rust"
-    },
-    {
-      "name": "keystore2_selinux_concurrency_test"
-    },
-    {
-      "name": "keystore2_test"
-    },
-    {
-      "name": "keystore2_test_utils_test"
-    },
-    {
-      "name": "legacykeystore_test"
-    },
-    {
       "name": "memoffset_test_src_lib"
-    },
-    {
-      "name": "microdroid_manager_test"
-    },
-    {
-      "name": "virtualizationservice_device_test"
     }
   ]
 }
diff --git a/build.rs b/build.rs
index 0604c19..e18810f 100644
--- a/build.rs
+++ b/build.rs
@@ -19,4 +19,7 @@
     if ac.probe_rustc_version(1, 51) {
         println!("cargo:rustc-cfg=raw_ref_macros");
     }
+    if ac.probe_rustc_version(1, 65) {
+        println!("cargo:rustc-cfg=stable_const");
+    }
 }
diff --git a/cargo2android.json b/cargo2android.json
index 5654962..b318e12 100644
--- a/cargo2android.json
+++ b/cargo2android.json
@@ -1,7 +1,7 @@
 {
   "apex-available": [
     "//apex_available:platform",
-    "com.android.bluetooth",
+    "com.android.btservices",
     "com.android.compos",
     "com.android.virt"
   ],
diff --git a/ci/miri.sh b/ci/miri.sh
deleted file mode 100755
index 5aea2ec..0000000
--- a/ci/miri.sh
+++ /dev/null
@@ -1,14 +0,0 @@
-set -ex
-
-# Install Miri.
-MIRI_NIGHTLY=nightly-$(curl -s https://rust-lang.github.io/rustup-components-history/x86_64-unknown-linux-gnu/miri)
-echo "Installing latest nightly with Miri: $MIRI_NIGHTLY"
-rustup default "$MIRI_NIGHTLY"
-rustup component add miri
-
-# Run tests.
-cargo miri test
-cargo miri test --all-features
-
-# Restore old state in case Travis uses this cache for other jobs.
-rustup default nightly
diff --git a/src/lib.rs b/src/lib.rs
index 1798d91..356595d 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -58,9 +58,10 @@
 // ANDROID: include standard library to build as a dylib
 //#![no_std]
 #![cfg_attr(
-    feature = "unstable_const",
-    feature(const_ptr_offset_from, const_refs_to_cell)
+    all(feature = "unstable_const", not(stable_const)),
+    feature(const_ptr_offset_from)
 )]
+#![cfg_attr(feature = "unstable_const", feature(const_refs_to_cell))]
 
 #[macro_use]
 #[cfg(doctests)]
diff --git a/src/offset_of.rs b/src/offset_of.rs
index 8596e45..9ce4ae2 100644
--- a/src/offset_of.rs
+++ b/src/offset_of.rs
@@ -46,7 +46,7 @@
 }
 
 /// Macro to compute the distance between two pointers.
-#[cfg(feature = "unstable_const")]
+#[cfg(any(feature = "unstable_const", stable_const))]
 #[macro_export]
 #[doc(hidden)]
 macro_rules! _memoffset_offset_from_unsafe {
@@ -58,7 +58,7 @@
         unsafe { (field as *const u8).offset_from(base as *const u8) as usize }
     }};
 }
-#[cfg(not(feature = "unstable_const"))]
+#[cfg(not(any(feature = "unstable_const", stable_const)))]
 #[macro_export]
 #[doc(hidden)]
 macro_rules! _memoffset_offset_from_unsafe {
@@ -86,6 +86,16 @@
 ///     assert_eq!(offset_of!(Foo, b), 4);
 /// }
 /// ```
+///
+/// ## Notes
+/// Rust's ABI is unstable, and [type layout can be changed with each
+/// compilation](https://doc.rust-lang.org/reference/type-layout.html).
+///
+/// Using `offset_of!` with a `repr(Rust)` struct will return the correct offset of the
+/// specified `field` for a particular compilation, but the exact value may change
+/// based on the compiler version, concrete struct type, time of day, or rustc's mood.
+///
+/// As a result, the value should not be retained and used between different compilations.
 #[macro_export(local_inner_macros)]
 macro_rules! offset_of {
     ($parent:path, $field:tt) => {{
@@ -121,6 +131,39 @@
     }};
 }
 
+/// Calculates the offset of the specified union member from the start of the union.
+///
+/// ## Examples
+/// ```
+/// use memoffset::offset_of_union;
+///
+/// #[repr(C, packed)]
+/// union Foo {
+///     foo32: i32,
+///     foo64: i64,
+/// }
+///
+/// fn main() {
+///     assert!(offset_of_union!(Foo, foo64) == 0);
+/// }
+/// ```
+///
+/// ## Note
+/// Due to macro_rules limitations, this macro will accept structs with a single field as well as unions.
+/// This is not a stable guarantee, and future versions of this crate might fail
+/// on any use of this macro with a struct, without a semver bump.
+#[macro_export(local_inner_macros)]
+macro_rules! offset_of_union {
+    ($parent:path, $field:tt) => {{
+        // Get a base pointer (non-dangling if rustc supports `MaybeUninit`).
+        _memoffset__let_base_ptr!(base_ptr, $parent);
+        // Get field pointer.
+        let field_ptr = raw_field_union!(base_ptr, $parent, $field);
+        // Compute offset.
+        _memoffset_offset_from_unsafe!(field_ptr, base_ptr)
+    }};
+}
+
 #[cfg(test)]
 mod tests {
     #[test]
@@ -162,6 +205,21 @@
     }
 
     #[test]
+    fn offset_union() {
+        // Since we're specifying repr(C), all fields are supposed to be at offset 0
+        #[repr(C)]
+        union Foo {
+            a: u32,
+            b: [u8; 2],
+            c: i64,
+        }
+
+        assert_eq!(offset_of_union!(Foo, a), 0);
+        assert_eq!(offset_of_union!(Foo, b), 0);
+        assert_eq!(offset_of_union!(Foo, c), 0);
+    }
+
+    #[test]
     fn path() {
         mod sub {
             #[repr(C)]
@@ -238,7 +296,23 @@
         );
     }
 
-    #[cfg(feature = "unstable_const")]
+    #[test]
+    fn test_raw_field_union() {
+        #[repr(C)]
+        union Foo {
+            a: u32,
+            b: [u8; 2],
+            c: i64,
+        }
+
+        let f = Foo { a: 0 };
+        let f_ptr = &f as *const _;
+        assert_eq!(f_ptr as usize + 0, raw_field_union!(f_ptr, Foo, a) as usize);
+        assert_eq!(f_ptr as usize + 0, raw_field_union!(f_ptr, Foo, b) as usize);
+        assert_eq!(f_ptr as usize + 0, raw_field_union!(f_ptr, Foo, c) as usize);
+    }
+
+    #[cfg(any(feature = "unstable_const", stable_const))]
     #[test]
     fn const_offset() {
         #[repr(C)]
@@ -263,7 +337,7 @@
         assert_eq!([0; offset_of!(Foo, b)].len(), 4);
     }
 
-    #[cfg(feature = "unstable_const")]
+    #[cfg(any(feature = "unstable_const", stable_const))]
     #[test]
     fn const_fn_offset() {
         const fn test_fn() -> usize {
diff --git a/src/raw_field.rs b/src/raw_field.rs
index a8dd2b3..e16df9f 100644
--- a/src/raw_field.rs
+++ b/src/raw_field.rs
@@ -39,6 +39,21 @@
 }
 
 /// Deref-coercion protection macro.
+///
+/// Prevents complilation if the specified field name is not a part of the
+/// struct definition.
+///
+/// ```compile_fail
+/// use memoffset::_memoffset__field_check;
+///
+/// struct Foo {
+///     foo: i32,
+/// }
+///
+/// type BoxedFoo = Box<Foo>;
+///
+/// _memoffset__field_check!(BoxedFoo, foo);
+/// ```
 #[cfg(allow_clippy)]
 #[macro_export]
 #[doc(hidden)]
@@ -64,6 +79,25 @@
 }
 
 /// Deref-coercion protection macro.
+///
+/// Prevents complilation if the specified type is not a tuple.
+///
+/// ```compile_fail
+/// use memoffset::_memoffset__field_check_tuple;
+///
+/// _memoffset__field_check_tuple!(i32, 0);
+/// ```
+#[cfg(allow_clippy)]
+#[macro_export]
+#[doc(hidden)]
+macro_rules! _memoffset__field_check_tuple {
+    ($type:ty, $field:tt) => {
+        // Make sure the type argument is a tuple
+        #[allow(clippy::unneeded_wildcard_pattern)]
+        let (_, ..): $type;
+    };
+}
+#[cfg(not(allow_clippy))]
 #[macro_export]
 #[doc(hidden)]
 macro_rules! _memoffset__field_check_tuple {
@@ -73,6 +107,53 @@
     };
 }
 
+/// Deref-coercion protection macro for unions.
+/// Unfortunately accepts single-field structs as well, which is not ideal,
+/// but ultimately pretty harmless.
+///
+/// ```compile_fail
+/// use memoffset::_memoffset__field_check_union;
+///
+/// union Foo {
+///     variant_a: i32,
+/// }
+///
+/// type BoxedFoo = Box<Foo>;
+///
+/// _memoffset__field_check_union!(BoxedFoo, variant_a);
+/// ```
+#[cfg(allow_clippy)]
+#[macro_export]
+#[doc(hidden)]
+macro_rules! _memoffset__field_check_union {
+    ($type:path, $field:tt) => {
+        // Make sure the field actually exists. This line ensures that a
+        // compile-time error is generated if $field is accessed through a
+        // Deref impl.
+        #[allow(clippy::unneeded_wildcard_pattern)]
+        // rustc1.19 requires unsafe here for the pattern; not needed in newer versions
+        #[allow(unused_unsafe)]
+        unsafe {
+            let $type { $field: _ };
+        }
+    };
+}
+#[cfg(not(allow_clippy))]
+#[macro_export]
+#[doc(hidden)]
+macro_rules! _memoffset__field_check_union {
+    ($type:path, $field:tt) => {
+        // Make sure the field actually exists. This line ensures that a
+        // compile-time error is generated if $field is accessed through a
+        // Deref impl.
+        // rustc1.19 requires unsafe here for the pattern; not needed in newer versions
+        #[allow(unused_unsafe)]
+        unsafe {
+            let $type { $field: _ };
+        }
+    };
+}
+
 /// Computes a const raw pointer to the given field of the given base pointer
 /// to the given parent type.
 ///
@@ -115,3 +196,31 @@
         }
     }};
 }
+
+/// Computes a const raw pointer to the given field of the given base pointer
+/// to the given parent tuple typle.
+///
+/// The `base` pointer *must not* be dangling, but it *may* point to
+/// uninitialized memory.
+///
+/// ## Note
+/// This macro is the same as `raw_field`, except for a different Deref-coercion check that
+/// supports unions.
+/// Due to macro_rules limitations, this check will accept structs with a single field as well as unions.
+/// This is not a stable guarantee, and future versions of this crate might fail
+/// on any use of this macro with a struct, without a semver bump.
+#[macro_export(local_inner_macros)]
+macro_rules! raw_field_union {
+    ($base:expr, $parent:path, $field:tt) => {{
+        _memoffset__field_check_union!($parent, $field);
+        let base = $base; // evaluate $base outside the `unsafe` block
+
+        // Get the field address.
+        // Crucially, we know that this will not trigger a deref coercion because
+        // of the field check we did above.
+        #[allow(unused_unsafe)] // for when the macro is used in an unsafe block
+        unsafe {
+            _memoffset__addr_of!((*(base as *const $parent)).$field)
+        }
+    }};
+}
diff --git a/src/span_of.rs b/src/span_of.rs
index a3663d5..c2030b7 100644
--- a/src/span_of.rs
+++ b/src/span_of.rs
@@ -52,11 +52,18 @@
 /// span_of!(Struct, start ..)
 /// ```
 ///
-/// *Note*:
+/// ### Note
 /// This macro uses recursion in order to resolve the range expressions, so there is a limit to
 /// the complexity of the expression.
 /// In order to raise the limit, the compiler's recursion limit should be lifted.
 ///
+/// ### Safety
+/// The inter-field form mentioned above assumes that the first field is positioned before the
+/// second.
+/// This is only guarenteed for `repr(C)` structs.
+/// Usage with `repr(Rust)` structs may yield unexpected results, like downward-going ranges,
+/// spans that include unexpected fields, empty spans, or spans that include *unexpected* padding bytes.
+///
 /// ## Examples
 /// ```
 /// use memoffset::span_of;