aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Maurer <mmaurer@google.com>2023-05-26 20:23:00 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2023-05-26 20:23:00 +0000
commit87a2a96f7ed7b2f0edf7765d73e454c4d27fa5e1 (patch)
tree44329ab8b9d5e6bdf8ce70f2540af661028c62ea
parentcbbe1f7e1e9477b21993662b8daad783ff956c1e (diff)
parent5106d362ec9e61d8cad0a6cc380a56c6e931b088 (diff)
downloadzeroize_derive-87a2a96f7ed7b2f0edf7765d73e454c4d27fa5e1.tar.gz
Update to syn-2 am: 5106d362ec
Original change: https://android-review.googlesource.com/c/platform/external/rust/crates/zeroize_derive/+/2520383 Change-Id: I12183e8ed7eee922c797f003a0928f9c9e9394dc Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r--Android.bp6
-rw-r--r--src/lib.rs587
2 files changed, 302 insertions, 291 deletions
diff --git a/Android.bp b/Android.bp
index 6e10664..84eb942 100644
--- a/Android.bp
+++ b/Android.bp
@@ -26,12 +26,11 @@ rust_proc_macro {
cargo_env_compat: true,
cargo_pkg_version: "1.3.3",
srcs: ["src/lib.rs"],
- edition: "2018",
+ edition: "2021",
rustlibs: [
"libproc_macro2",
"libquote",
"libsyn",
- "libsynstructure",
],
compile_multilib: "first",
product_available: true,
@@ -49,11 +48,10 @@ rust_test_host {
test_options: {
unit_test: true,
},
- edition: "2018",
+ edition: "2021",
rustlibs: [
"libproc_macro2",
"libquote",
"libsyn",
- "libsynstructure",
],
}
diff --git a/src/lib.rs b/src/lib.rs
index baf6990..3679055 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -3,91 +3,110 @@
#![crate_type = "proc-macro"]
#![forbid(unsafe_code)]
#![warn(rust_2018_idioms, trivial_casts, unused_qualifications)]
+extern crate proc_macro;
-use proc_macro2::TokenStream;
-use quote::quote;
+use proc_macro2::{Ident, TokenStream};
+use quote::{format_ident, quote};
use syn::{
parse::{Parse, ParseStream},
punctuated::Punctuated,
token::Comma,
- Attribute, Lit, Meta, NestedMeta, Result, WherePredicate,
+ Attribute, Data, DeriveInput, Expr, ExprLit, Field, Fields, Lit, Meta, Result, Variant,
+ WherePredicate,
};
-use synstructure::{decl_derive, AddBounds, BindStyle, BindingInfo, VariantInfo};
-
-decl_derive!(
- [Zeroize, attributes(zeroize)] =>
-
- /// Derive the `Zeroize` trait.
- ///
- /// Supports the following attributes:
- ///
- /// On the item level:
- /// - `#[zeroize(drop)]`: *deprecated* use `ZeroizeOnDrop` instead
- /// - `#[zeroize(bound = "T: MyTrait")]`: this replaces any trait bounds
- /// inferred by zeroize-derive
- ///
- /// On the field level:
- /// - `#[zeroize(skip)]`: skips this field or variant when calling `zeroize()`
- derive_zeroize
-);
-
-decl_derive!(
- [ZeroizeOnDrop, attributes(zeroize)] =>
-
- /// Derive the `ZeroizeOnDrop` trait.
- ///
- /// Supports the following attributes:
- ///
- /// On the field level:
- /// - `#[zeroize(skip)]`: skips this field or variant when calling `zeroize()`
- derive_zeroize_on_drop
-);
/// Name of zeroize-related attributes
const ZEROIZE_ATTR: &str = "zeroize";
-/// Custom derive for `Zeroize`
-fn derive_zeroize(mut s: synstructure::Structure<'_>) -> TokenStream {
- let attributes = ZeroizeAttrs::parse(&s);
+/// Derive the `Zeroize` trait.
+///
+/// Supports the following attributes:
+///
+/// On the item level:
+/// - `#[zeroize(drop)]`: *deprecated* use `ZeroizeOnDrop` instead
+/// - `#[zeroize(bound = "T: MyTrait")]`: this replaces any trait bounds
+/// inferred by zeroize-derive
+///
+/// On the field level:
+/// - `#[zeroize(skip)]`: skips this field or variant when calling `zeroize()`
+#[proc_macro_derive(Zeroize, attributes(zeroize))]
+pub fn derive_zeroize(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
+ derive_zeroize_impl(syn::parse_macro_input!(input as DeriveInput)).into()
+}
- if let Some(bounds) = attributes.bound {
- s.add_bounds(AddBounds::None);
+fn derive_zeroize_impl(input: DeriveInput) -> TokenStream {
+ let attributes = ZeroizeAttrs::parse(&input);
- for bound in bounds.0 {
- s.add_where_predicate(bound);
- }
- }
+ let extra_bounds = match attributes.bound {
+ Some(bounds) => bounds.0,
+ None => Default::default(),
+ };
+
+ let mut generics = input.generics.clone();
+ generics.make_where_clause().predicates.extend(extra_bounds);
- // NOTE: These are split into named functions to simplify testing with
- // synstructure's `test_derive!` macro.
- if attributes.drop {
- derive_zeroize_with_drop(s)
+ let ty_name = &input.ident;
+
+ let (impl_gen, type_gen, where_) = generics.split_for_impl();
+
+ let drop_impl = if attributes.drop {
+ quote! {
+ #[doc(hidden)]
+ impl #impl_gen Drop for #ty_name #type_gen #where_ {
+ fn drop(&mut self) {
+ self.zeroize()
+ }
+ }
+ }
} else {
- derive_zeroize_without_drop(s)
+ quote! {}
+ };
+
+ let zeroizers = generate_fields(&input, quote! { zeroize });
+ let zeroize_impl = quote! {
+ impl #impl_gen ::zeroize::Zeroize for #ty_name #type_gen #where_ {
+ fn zeroize(&mut self) {
+ #zeroizers
+ }
+ }
+ };
+
+ quote! {
+ #zeroize_impl
+ #drop_impl
}
}
-/// Custom derive for `ZeroizeOnDrop`
-fn derive_zeroize_on_drop(mut s: synstructure::Structure<'_>) -> TokenStream {
- let zeroizers = generate_fields(&mut s, quote! { zeroize_or_on_drop });
+/// Derive the `ZeroizeOnDrop` trait.
+///
+/// Supports the following attributes:
+///
+/// On the field level:
+/// - `#[zeroize(skip)]`: skips this field or variant when calling `zeroize()`
+#[proc_macro_derive(ZeroizeOnDrop, attributes(zeroize))]
+pub fn derive_zeroize_on_drop(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
+ derive_zeroize_on_drop_impl(syn::parse_macro_input!(input as DeriveInput)).into()
+}
+
+fn derive_zeroize_on_drop_impl(input: DeriveInput) -> TokenStream {
+ let zeroizers = generate_fields(&input, quote! { zeroize_or_on_drop });
+
+ let (impl_gen, type_gen, where_) = input.generics.split_for_impl();
+ let name = input.ident.clone();
- let drop_impl = s.add_bounds(AddBounds::None).gen_impl(quote! {
- gen impl Drop for @Self {
+ let drop_impl = quote! {
+ impl #impl_gen Drop for #name #type_gen #where_ {
fn drop(&mut self) {
- use zeroize::__internal::AssertZeroize;
- use zeroize::__internal::AssertZeroizeOnDrop;
- match self {
- #zeroizers
- }
+ use ::zeroize::__internal::AssertZeroize;
+ use ::zeroize::__internal::AssertZeroizeOnDrop;
+ #zeroizers
}
}
- });
-
- let zeroize_on_drop_impl = impl_zeroize_on_drop(&s);
+ };
+ let zeroize_on_drop_impl = impl_zeroize_on_drop(&input);
quote! {
#drop_impl
-
#zeroize_on_drop_impl
}
}
@@ -112,40 +131,42 @@ impl Parse for Bounds {
impl ZeroizeAttrs {
/// Parse attributes from the incoming AST
- fn parse(s: &synstructure::Structure<'_>) -> Self {
+ fn parse(input: &DeriveInput) -> Self {
let mut result = Self::default();
- for attr in s.ast().attrs.iter() {
+ for attr in &input.attrs {
result.parse_attr(attr, None, None);
}
- for v in s.variants().iter() {
- // only process actual enum variants here, as we don't want to process struct attributes twice
- if v.prefix.is_some() {
- for attr in v.ast().attrs.iter() {
- result.parse_attr(attr, Some(v), None);
+
+ match &input.data {
+ syn::Data::Enum(enum_) => {
+ for variant in &enum_.variants {
+ for attr in &variant.attrs {
+ result.parse_attr(attr, Some(variant), None);
+ }
+ for field in &variant.fields {
+ for attr in &field.attrs {
+ result.parse_attr(attr, Some(variant), Some(field));
+ }
+ }
}
}
- for binding in v.bindings().iter() {
- for attr in binding.ast().attrs.iter() {
- result.parse_attr(attr, Some(v), Some(binding));
+ syn::Data::Struct(struct_) => {
+ for field in &struct_.fields {
+ for attr in &field.attrs {
+ result.parse_attr(attr, None, Some(field));
+ }
}
}
+ syn::Data::Union(union_) => panic!("Unsupported untagged union {:?}", union_),
}
result
}
/// Parse attribute and handle `#[zeroize(...)]` attributes
- fn parse_attr(
- &mut self,
- attr: &Attribute,
- variant: Option<&VariantInfo<'_>>,
- binding: Option<&BindingInfo<'_>>,
- ) {
- let meta_list = match attr
- .parse_meta()
- .unwrap_or_else(|e| panic!("error parsing attribute: {:?} ({})", attr, e))
- {
+ fn parse_attr(&mut self, attr: &Attribute, variant: Option<&Variant>, binding: Option<&Field>) {
+ let meta_list = match &attr.meta {
Meta::List(list) => list,
_ => return,
};
@@ -155,29 +176,23 @@ impl ZeroizeAttrs {
return;
}
- for nested_meta in &meta_list.nested {
- if let NestedMeta::Meta(meta) = nested_meta {
- self.parse_meta(meta, variant, binding);
- } else {
- panic!("malformed #[zeroize] attribute: {:?}", nested_meta);
- }
+ for meta in attr
+ .parse_args_with(Punctuated::<Meta, Comma>::parse_terminated)
+ .unwrap_or_else(|e| panic!("error parsing attribute: {:?} ({})", attr, e))
+ {
+ self.parse_meta(&meta, variant, binding);
}
}
/// Parse `#[zeroize(...)]` attribute metadata (e.g. `drop`)
- fn parse_meta(
- &mut self,
- meta: &Meta,
- variant: Option<&VariantInfo<'_>>,
- binding: Option<&BindingInfo<'_>>,
- ) {
+ fn parse_meta(&mut self, meta: &Meta, variant: Option<&Variant>, binding: Option<&Field>) {
if meta.path().is_ident("drop") {
assert!(!self.drop, "duplicate #[zeroize] drop flags");
match (variant, binding) {
(_variant, Some(_binding)) => {
// structs don't have a variant prefix, and only structs have bindings outside of a variant
- let item_kind = match variant.and_then(|variant| variant.prefix) {
+ let item_kind = match variant {
Some(_) => "enum",
None => "struct",
};
@@ -203,7 +218,7 @@ impl ZeroizeAttrs {
match (variant, binding) {
(_variant, Some(_binding)) => {
// structs don't have a variant prefix, and only structs have bindings outside of a variant
- let item_kind = match variant.and_then(|variant| variant.prefix) {
+ let item_kind = match variant {
Some(_) => "enum",
None => "struct",
};
@@ -221,7 +236,10 @@ impl ZeroizeAttrs {
)),
(None, None) => {
if let Meta::NameValue(meta_name_value) = meta {
- if let Lit::Str(lit) = &meta_name_value.lit {
+ if let Expr::Lit(ExprLit {
+ lit: Lit::Str(lit), ..
+ }) = &meta_name_value.value
+ {
if lit.value().is_empty() {
self.bound = Some(Bounds(Punctuated::new()));
} else {
@@ -253,277 +271,278 @@ impl ZeroizeAttrs {
}
}
-fn generate_fields(s: &mut synstructure::Structure<'_>, method: TokenStream) -> TokenStream {
- s.bind_with(|_| BindStyle::RefMut);
+fn field_ident(n: usize, field: &Field) -> Ident {
+ if let Some(ref name) = field.ident {
+ name.clone()
+ } else {
+ format_ident!("__zeroize_field_{}", n)
+ }
+}
- s.filter_variants(|vi| {
- let result = filter_skip(vi.ast().attrs, true);
+fn generate_fields(input: &DeriveInput, method: TokenStream) -> TokenStream {
+ let input_id = &input.ident;
+ let fields: Vec<_> = match input.data {
+ Data::Enum(ref enum_) => enum_
+ .variants
+ .iter()
+ .filter_map(|variant| {
+ if attr_skip(&variant.attrs) {
+ if variant.fields.iter().any(|field| attr_skip(&field.attrs)) {
+ panic!("duplicate #[zeroize] skip flags")
+ }
+ None
+ } else {
+ let variant_id = &variant.ident;
+ Some((quote! { #input_id :: #variant_id }, &variant.fields))
+ }
+ })
+ .collect(),
+ Data::Struct(ref struct_) => vec![(quote! { #input_id }, &struct_.fields)],
+ Data::Union(ref union_) => panic!("Cannot generate fields for untagged union {:?}", union_),
+ };
+
+ let arms = fields.into_iter().map(|(name, fields)| {
+ let method_field = fields.iter().enumerate().filter_map(|(n, field)| {
+ if attr_skip(&field.attrs) {
+ None
+ } else {
+ let name = field_ident(n, field);
+ Some(quote! { #name.#method() })
+ }
+ });
+
+ let field_bindings = fields
+ .iter()
+ .enumerate()
+ .map(|(n, field)| field_ident(n, field));
+
+ let binding = match fields {
+ Fields::Named(_) => quote! {
+ #name { #(#field_bindings),* }
+ },
+ Fields::Unnamed(_) => quote! {
+ #name ( #(#field_bindings),* )
+ },
+ Fields::Unit => quote! {
+ #name
+ },
+ };
- // check for duplicate `#[zeroize(skip)]` attributes in nested variants
- for field in vi.ast().fields {
- filter_skip(&field.attrs, result);
+ quote! {
+ #[allow(unused_variables)]
+ #binding => {
+ #(#method_field);*
+ }
}
+ });
- result
- })
- .filter(|bi| filter_skip(&bi.ast().attrs, true))
- .each(|bi| quote! { #bi.#method(); })
+ quote! {
+ match self {
+ #(#arms),*
+ _ => {}
+ }
+ }
}
-fn filter_skip(attrs: &[Attribute], start: bool) -> bool {
- let mut result = start;
-
- for attr in attrs.iter().filter_map(|attr| attr.parse_meta().ok()) {
+fn attr_skip(attrs: &[Attribute]) -> bool {
+ let mut result = false;
+ for attr in attrs.iter().map(|attr| &attr.meta) {
if let Meta::List(list) = attr {
if list.path.is_ident(ZEROIZE_ATTR) {
- for nested in list.nested {
- if let NestedMeta::Meta(Meta::Path(path)) = nested {
+ for meta in list
+ .parse_args_with(Punctuated::<Meta, Comma>::parse_terminated)
+ .unwrap_or_else(|e| panic!("error parsing attribute: {:?} ({})", list, e))
+ {
+ if let Meta::Path(path) = meta {
if path.is_ident("skip") {
- assert!(result, "duplicate #[zeroize] skip flags");
- result = false;
+ assert!(!result, "duplicate #[zeroize] skip flags");
+ result = true;
}
}
}
}
}
}
-
result
}
-/// Custom derive for `Zeroize` (without `Drop`)
-fn derive_zeroize_without_drop(mut s: synstructure::Structure<'_>) -> TokenStream {
- let zeroizers = generate_fields(&mut s, quote! { zeroize });
-
- s.bound_impl(
- quote!(zeroize::Zeroize),
- quote! {
- fn zeroize(&mut self) {
- match self {
- #zeroizers
- }
- }
- },
- )
-}
-
-/// Custom derive for `Zeroize` and `Drop`
-fn derive_zeroize_with_drop(s: synstructure::Structure<'_>) -> TokenStream {
- let drop_impl = s.gen_impl(quote! {
- gen impl Drop for @Self {
- fn drop(&mut self) {
- self.zeroize();
- }
- }
- });
-
- let zeroize_impl = derive_zeroize_without_drop(s);
-
+fn impl_zeroize_on_drop(input: &DeriveInput) -> TokenStream {
+ let name = input.ident.clone();
+ let (impl_gen, type_gen, where_) = input.generics.split_for_impl();
quote! {
- #zeroize_impl
-
#[doc(hidden)]
- #drop_impl
+ impl #impl_gen ::zeroize::ZeroizeOnDrop for #name #type_gen #where_ {}
}
}
-fn impl_zeroize_on_drop(s: &synstructure::Structure<'_>) -> TokenStream {
- #[allow(unused_qualifications)]
- s.bound_impl(quote!(zeroize::ZeroizeOnDrop), Option::<TokenStream>::None)
-}
-
#[cfg(test)]
mod tests {
use super::*;
- use syn::parse_str;
- use synstructure::{test_derive, Structure};
+
+ #[track_caller]
+ fn test_derive(
+ f: impl Fn(DeriveInput) -> TokenStream,
+ input: TokenStream,
+ expected_output: TokenStream,
+ ) {
+ let output = f(syn::parse2(input).unwrap());
+ assert_eq!(format!("{output}"), format!("{expected_output}"));
+ }
+
+ #[track_caller]
+ fn parse_zeroize_test(unparsed: &str) -> TokenStream {
+ derive_zeroize_impl(syn::parse_str(unparsed).expect("Failed to parse test input"))
+ }
#[test]
fn zeroize_without_drop() {
- test_derive! {
- derive_zeroize_without_drop {
+ test_derive(
+ derive_zeroize_impl,
+ quote! {
struct Z {
a: String,
b: Vec<u8>,
c: [u8; 3],
}
- }
- expands to {
- #[allow(non_upper_case_globals)]
- #[doc(hidden)]
- const _DERIVE_zeroize_Zeroize_FOR_Z: () = {
- extern crate zeroize;
- impl zeroize::Zeroize for Z {
- fn zeroize(&mut self) {
- match self {
- Z {
- a: ref mut __binding_0,
- b: ref mut __binding_1,
- c: ref mut __binding_2,
- } => {
- { __binding_0.zeroize(); }
- { __binding_1.zeroize(); }
- { __binding_2.zeroize(); }
- }
+ },
+ quote! {
+ impl ::zeroize::Zeroize for Z {
+ fn zeroize(&mut self) {
+ match self {
+ #[allow(unused_variables)]
+ Z { a, b, c } => {
+ a.zeroize();
+ b.zeroize();
+ c.zeroize()
}
+ _ => {}
}
}
- };
- }
- no_build // tests the code compiles are in the `zeroize` crate
- }
+ }
+ },
+ )
}
#[test]
fn zeroize_with_drop() {
- test_derive! {
- derive_zeroize_with_drop {
+ test_derive(
+ derive_zeroize_impl,
+ quote! {
+ #[zeroize(drop)]
struct Z {
a: String,
b: Vec<u8>,
c: [u8; 3],
}
- }
- expands to {
- #[allow(non_upper_case_globals)]
- #[doc(hidden)]
- const _DERIVE_zeroize_Zeroize_FOR_Z: () = {
- extern crate zeroize;
- impl zeroize::Zeroize for Z {
- fn zeroize(&mut self) {
- match self {
- Z {
- a: ref mut __binding_0,
- b: ref mut __binding_1,
- c: ref mut __binding_2,
- } => {
- { __binding_0.zeroize(); }
- { __binding_1.zeroize(); }
- { __binding_2.zeroize(); }
- }
+ },
+ quote! {
+ impl ::zeroize::Zeroize for Z {
+ fn zeroize(&mut self) {
+ match self {
+ #[allow(unused_variables)]
+ Z { a, b, c } => {
+ a.zeroize();
+ b.zeroize();
+ c.zeroize()
}
+ _ => {}
}
}
- };
+ }
#[doc(hidden)]
- #[allow(non_upper_case_globals)]
- const _DERIVE_Drop_FOR_Z: () = {
- impl Drop for Z {
- fn drop(&mut self) {
- self.zeroize();
- }
+ impl Drop for Z {
+ fn drop(&mut self) {
+ self.zeroize()
}
- };
- }
- no_build // tests the code compiles are in the `zeroize` crate
- }
+ }
+ },
+ )
}
#[test]
fn zeroize_with_skip() {
- test_derive! {
- derive_zeroize_without_drop {
+ test_derive(
+ derive_zeroize_impl,
+ quote! {
struct Z {
a: String,
b: Vec<u8>,
#[zeroize(skip)]
c: [u8; 3],
}
- }
- expands to {
- #[allow(non_upper_case_globals)]
- #[doc(hidden)]
- const _DERIVE_zeroize_Zeroize_FOR_Z: () = {
- extern crate zeroize;
- impl zeroize::Zeroize for Z {
- fn zeroize(&mut self) {
- match self {
- Z {
- a: ref mut __binding_0,
- b: ref mut __binding_1,
- ..
- } => {
- { __binding_0.zeroize(); }
- { __binding_1.zeroize(); }
- }
+ },
+ quote! {
+ impl ::zeroize::Zeroize for Z {
+ fn zeroize(&mut self) {
+ match self {
+ #[allow(unused_variables)]
+ Z { a, b, c } => {
+ a.zeroize();
+ b.zeroize()
}
+ _ => {}
}
}
- };
- }
- no_build // tests the code compiles are in the `zeroize` crate
- }
+ }
+ },
+ )
}
#[test]
fn zeroize_with_bound() {
- test_derive! {
- derive_zeroize {
+ test_derive(
+ derive_zeroize_impl,
+ quote! {
#[zeroize(bound = "T: MyTrait")]
struct Z<T>(T);
- }
- expands to {
- #[allow(non_upper_case_globals)]
- #[doc(hidden)]
- const _DERIVE_zeroize_Zeroize_FOR_Z: () = {
- extern crate zeroize;
- impl<T> zeroize::Zeroize for Z<T>
- where T: MyTrait
- {
- fn zeroize(&mut self) {
- match self {
- Z(ref mut __binding_0,) => {
- { __binding_0.zeroize(); }
- }
+ },
+ quote! {
+ impl<T> ::zeroize::Zeroize for Z<T> where T: MyTrait {
+ fn zeroize(&mut self) {
+ match self {
+ #[allow(unused_variables)]
+ Z(__zeroize_field_0) => {
+ __zeroize_field_0.zeroize()
}
+ _ => {}
}
}
- };
- }
- no_build // tests the code compiles are in the `zeroize` crate
- }
+ }
+ },
+ )
}
#[test]
fn zeroize_only_drop() {
- test_derive! {
- derive_zeroize_on_drop {
+ test_derive(
+ derive_zeroize_on_drop_impl,
+ quote! {
struct Z {
a: String,
b: Vec<u8>,
c: [u8; 3],
}
- }
- expands to {
- #[allow(non_upper_case_globals)]
- const _DERIVE_Drop_FOR_Z: () = {
- impl Drop for Z {
- fn drop(&mut self) {
- use zeroize::__internal::AssertZeroize;
- use zeroize::__internal::AssertZeroizeOnDrop;
- match self {
- Z {
- a: ref mut __binding_0,
- b: ref mut __binding_1,
- c: ref mut __binding_2,
- } => {
- { __binding_0.zeroize_or_on_drop(); }
- { __binding_1.zeroize_or_on_drop(); }
- { __binding_2.zeroize_or_on_drop(); }
- }
+ },
+ quote! {
+ impl Drop for Z {
+ fn drop(&mut self) {
+ use ::zeroize::__internal::AssertZeroize;
+ use ::zeroize::__internal::AssertZeroizeOnDrop;
+ match self {
+ #[allow(unused_variables)]
+ Z { a, b, c } => {
+ a.zeroize_or_on_drop();
+ b.zeroize_or_on_drop();
+ c.zeroize_or_on_drop()
}
+ _ => {}
}
}
- };
- #[allow(non_upper_case_globals)]
+ }
#[doc(hidden)]
- const _DERIVE_zeroize_ZeroizeOnDrop_FOR_Z: () = {
- extern crate zeroize;
- impl zeroize::ZeroizeOnDrop for Z {}
- };
- }
- no_build // tests the code compiles are in the `zeroize` crate
- }
+ impl ::zeroize::ZeroizeOnDrop for Z {}
+ },
+ )
}
#[test]
@@ -801,10 +820,4 @@ mod tests {
struct Z<T>(T);
));
}
-
- fn parse_zeroize_test(unparsed: &str) -> TokenStream {
- derive_zeroize(Structure::new(
- &parse_str(unparsed).expect("Failed to parse test input"),
- ))
- }
}