diff options
author | Frederick Mayle <fmayle@google.com> | 2023-09-28 16:20:43 -0700 |
---|---|---|
committer | Frederick Mayle <fmayle@google.com> | 2023-10-12 14:23:48 -0700 |
commit | 65b2dfba54d6aad522cb1e68473ac73606c34a6e (patch) | |
tree | 5ee455d88a857f173887c1d54e2543929fff7b81 | |
parent | ed92e3395a5662c8cc764adb42be000e8799ccf4 (diff) | |
download | zerocopy-derive-65b2dfba54d6aad522cb1e68473ac73606c34a6e.tar.gz |
Upgrade zerocopy-derive to 0.7.5
This project was upgraded with external_updater.
Usage: tools/external_updater/updater.sh update rust/crates/zerocopy-derive
For more info, check https://cs.android.com/android/platform/superproject/+/main:tools/external_updater/README.md
Bug: 302709631
Test: TreeHugger
Change-Id: I9b1109b3083cc6cac812be9c2c4f4ba5c22d7749
61 files changed, 1974 insertions, 1054 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json index 99908cd..0273786 100644 --- a/.cargo_vcs_info.json +++ b/.cargo_vcs_info.json @@ -1,6 +1,6 @@ { "git": { - "sha1": "8efbd0038df30e39cba9f6df6cb4577571dcc3d8" + "sha1": "c150d4f1b75fc21240574b6b7dbbcdc236d388b0" }, "path_in_vcs": "zerocopy-derive" }
\ No newline at end of file @@ -24,9 +24,9 @@ rust_proc_macro { name: "libzerocopy_derive", crate_name: "zerocopy_derive", cargo_env_compat: true, - cargo_pkg_version: "0.3.2", + cargo_pkg_version: "0.7.5", srcs: ["src/lib.rs"], - edition: "2018", + edition: "2021", rustlibs: [ "libproc_macro2", "libquote", @@ -10,13 +10,14 @@ # See Cargo.toml.orig for the original contents. [package] -edition = "2018" +edition = "2021" +rust-version = "1.61.0" name = "zerocopy-derive" -version = "0.3.2" +version = "0.7.5" authors = ["Joshua Liebow-Feeser <joshlf@google.com>"] exclude = [".*"] description = "Custom derive for traits from the zerocopy crate" -license-file = "LICENSE" +license = "BSD-2-Clause" repository = "https://github.com/google/zerocopy" [lib] @@ -29,11 +30,13 @@ version = "1.0.1" version = "1.0.10" [dependencies.syn] -version = "2" -features = ["visit"] +version = "2.0.31" [dev-dependencies.rustversion] version = "1.0" +[dev-dependencies.static_assertions] +version = "1.1" + [dev-dependencies.trybuild] -version = "1.0" +version = "=1.0.80" diff --git a/Cargo.toml.orig b/Cargo.toml.orig index 1f7ec41..4cb0f08 100644 --- a/Cargo.toml.orig +++ b/Cargo.toml.orig @@ -1,39 +1,33 @@ -# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO -# -# 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. -# -# 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. +# Copyright 2019 The Fuchsia Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. [package] -edition = "2018" +edition = "2021" name = "zerocopy-derive" -version = "0.3.2" +version = "0.7.5" authors = ["Joshua Liebow-Feeser <joshlf@google.com>"] -exclude = [".*"] description = "Custom derive for traits from the zerocopy crate" -license-file = "LICENSE" +license = "BSD-2-Clause" repository = "https://github.com/google/zerocopy" +rust-version = "1.61.0" + +exclude = [".*"] [lib] proc-macro = true -[dependencies.proc-macro2] -version = "1.0.1" - -[dependencies.quote] -version = "1.0.10" - -[dependencies.syn] -version = "1.0.5" -features = ["visit"] - -[dev-dependencies.rustversion] -version = "1.0" +[dependencies] +proc-macro2 = "1.0.1" +quote = "1.0.10" +syn = "2.0.31" -[dev-dependencies.trybuild] -version = "1.0" +[dev-dependencies] +rustversion = "1.0" +static_assertions = "1.1" +# Pinned to a specific version so that the version used for local development +# and the version used in CI are guaranteed to be the same. Future versions +# sometimes change the output format slightly, so a version mismatch can cause +# CI test failures. +trybuild = "=1.0.80" +zerocopy = { path = "../", features = ["default", "derive"] } @@ -1,3 +1,7 @@ +# This project was upgraded with external_updater. +# Usage: tools/external_updater/updater.sh update rust/crates/zerocopy-derive +# For more info, check https://cs.android.com/android/platform/superproject/+/main:tools/external_updater/README.md + name: "zerocopy-derive" description: "Custom derive for traits from the zerocopy crate" third_party { @@ -7,13 +11,13 @@ third_party { } url { type: ARCHIVE - value: "https://static.crates.io/crates/zerocopy-derive/zerocopy-derive-0.3.2.crate" + value: "https://static.crates.io/crates/zerocopy-derive/zerocopy-derive-0.7.5.crate" } - version: "0.3.2" + version: "0.7.5" license_type: NOTICE last_upgrade_date { - year: 2022 - month: 11 - day: 18 + year: 2023 + month: 9 + day: 28 } } @@ -2,34 +2,39 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -use syn::{Data, DataEnum, DataStruct, DataUnion, Field, Fields, Type}; +use syn::{Data, DataEnum, DataStruct, DataUnion, Type}; pub trait DataExt { - fn nested_types(&self) -> Vec<&Type>; + /// Extract the types of all fields. For enums, extract the types of fields + /// from each variant. + fn field_types(&self) -> Vec<&Type>; } impl DataExt for Data { - fn nested_types(&self) -> Vec<&Type> { + fn field_types(&self) -> Vec<&Type> { match self { - Data::Struct(strc) => strc.nested_types(), - Data::Enum(enm) => enm.nested_types(), - Data::Union(un) => un.nested_types(), + Data::Struct(strc) => strc.field_types(), + Data::Enum(enm) => enm.field_types(), + Data::Union(un) => un.field_types(), } } } impl DataExt for DataStruct { - fn nested_types(&self) -> Vec<&Type> { - fields_to_types(&self.fields) + fn field_types(&self) -> Vec<&Type> { + self.fields.iter().map(|f| &f.ty).collect() } } impl DataExt for DataEnum { - fn nested_types(&self) -> Vec<&Type> { - self.variants.iter().map(|var| fields_to_types(&var.fields)).fold(Vec::new(), |mut a, b| { - a.extend(b); - a - }) + fn field_types(&self) -> Vec<&Type> { + self.variants.iter().flat_map(|var| &var.fields).map(|f| &f.ty).collect() + } +} + +impl DataExt for DataUnion { + fn field_types(&self) -> Vec<&Type> { + self.fields.named.iter().map(|f| &f.ty).collect() } } @@ -39,24 +44,6 @@ pub trait EnumExt { impl EnumExt for DataEnum { fn is_c_like(&self) -> bool { - self.nested_types().is_empty() + self.field_types().is_empty() } } - -impl DataExt for DataUnion { - fn nested_types(&self) -> Vec<&Type> { - field_iter_to_types(&self.fields.named) - } -} - -fn fields_to_types(fields: &Fields) -> Vec<&Type> { - match fields { - Fields::Named(named) => field_iter_to_types(&named.named), - Fields::Unnamed(unnamed) => field_iter_to_types(&unnamed.unnamed), - Fields::Unit => Vec::new(), - } -} - -fn field_iter_to_types<'a, I: IntoIterator<Item = &'a Field>>(fields: I) -> Vec<&'a Type> { - fields.into_iter().map(|f| &f.ty).collect() -} @@ -2,6 +2,26 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +//! Derive macros for [zerocopy]'s traits. +//! +//! [zerocopy]: https://docs.rs/zerocopy + +// Sometimes we want to use lints which were added after our MSRV. +// `unknown_lints` is `warn` by default and we deny warnings in CI, so without +// this attribute, any unknown lint would cause a CI failure when testing with +// our MSRV. +#![allow(unknown_lints)] +#![deny(renamed_and_removed_lints)] +#![deny(clippy::all, clippy::missing_safety_doc, clippy::undocumented_unsafe_blocks)] +#![deny( + rustdoc::bare_urls, + rustdoc::broken_intra_doc_links, + rustdoc::invalid_codeblock_attributes, + rustdoc::invalid_html_tags, + rustdoc::invalid_rust_codeblocks, + rustdoc::missing_crate_level_docs, + rustdoc::private_intra_doc_links +)] #![recursion_limit = "128"] mod ext; @@ -10,10 +30,9 @@ mod repr; use { proc_macro2::Span, quote::quote, - syn::visit::{self, Visit}, syn::{ - parse_quote, punctuated::Punctuated, token::Comma, Data, DataEnum, DataStruct, DataUnion, - DeriveInput, Error, GenericParam, Ident, Lifetime, Type, TypePath, + parse_quote, Data, DataEnum, DataStruct, DataUnion, DeriveInput, Error, Expr, ExprLit, + GenericParam, Ident, Lit, }, }; @@ -30,12 +49,23 @@ use {crate::ext::*, crate::repr::*}; // help: required by the derive of FromBytes // // Instead, we have more verbose error messages like "unsupported representation -// for deriving FromBytes, AsBytes, or Unaligned on an enum" +// for deriving FromZeroes, FromBytes, AsBytes, or Unaligned on an enum" // // This will probably require Span::error // (https://doc.rust-lang.org/nightly/proc_macro/struct.Span.html#method.error), // which is currently unstable. Revisit this once it's stable. +#[proc_macro_derive(FromZeroes)] +pub fn derive_from_zeroes(ts: proc_macro::TokenStream) -> proc_macro::TokenStream { + let ast = syn::parse_macro_input!(ts as DeriveInput); + match &ast.data { + Data::Struct(strct) => derive_from_zeroes_struct(&ast, strct), + Data::Enum(enm) => derive_from_zeroes_enum(&ast, enm), + Data::Union(unn) => derive_from_zeroes_union(&ast, unn), + } + .into() +} + #[proc_macro_derive(FromBytes)] pub fn derive_from_bytes(ts: proc_macro::TokenStream) -> proc_macro::TokenStream { let ast = syn::parse_macro_input!(ts as DeriveInput); @@ -87,11 +117,59 @@ const STRUCT_UNION_ALLOWED_REPR_COMBINATIONS: &[&[StructRepr]] = &[ &[StructRepr::C, StructRepr::Packed], ]; +// A struct is `FromZeroes` if: +// - all fields are `FromZeroes` + +fn derive_from_zeroes_struct(ast: &DeriveInput, strct: &DataStruct) -> proc_macro2::TokenStream { + impl_block(ast, strct, "FromZeroes", true, None) +} + +// An enum is `FromZeroes` if: +// - all of its variants are fieldless +// - one of the variants has a discriminant of `0` + +fn derive_from_zeroes_enum(ast: &DeriveInput, enm: &DataEnum) -> proc_macro2::TokenStream { + if !enm.is_c_like() { + return Error::new_spanned(ast, "only C-like enums can implement FromZeroes") + .to_compile_error(); + } + + let has_explicit_zero_discriminant = + enm.variants.iter().filter_map(|v| v.discriminant.as_ref()).any(|(_, e)| { + if let Expr::Lit(ExprLit { lit: Lit::Int(i), .. }) = e { + i.base10_parse::<usize>().ok() == Some(0) + } else { + false + } + }); + // If the first variant of an enum does not specify its discriminant, it is set to zero: + // https://doc.rust-lang.org/reference/items/enumerations.html#custom-discriminant-values-for-fieldless-enumerations + let has_implicit_zero_discriminant = + enm.variants.iter().next().map(|v| v.discriminant.is_none()) == Some(true); + + if !has_explicit_zero_discriminant && !has_implicit_zero_discriminant { + return Error::new_spanned( + ast, + "FromZeroes only supported on enums with a variant that has a discriminant of `0`", + ) + .to_compile_error(); + } + + impl_block(ast, enm, "FromZeroes", true, None) +} + +// Like structs, unions are `FromZeroes` if +// - all fields are `FromZeroes` + +fn derive_from_zeroes_union(ast: &DeriveInput, unn: &DataUnion) -> proc_macro2::TokenStream { + impl_block(ast, unn, "FromZeroes", true, None) +} + // A struct is `FromBytes` if: // - all fields are `FromBytes` fn derive_from_bytes_struct(ast: &DeriveInput, strct: &DataStruct) -> proc_macro2::TokenStream { - impl_block(ast, strct, "FromBytes", true, PaddingCheck::None) + impl_block(ast, strct, "FromBytes", true, None) } // An enum is `FromBytes` if: @@ -134,7 +212,7 @@ fn derive_from_bytes_enum(ast: &DeriveInput, enm: &DataEnum) -> proc_macro2::Tok .to_compile_error(); } - impl_block(ast, enm, "FromBytes", true, PaddingCheck::None) + impl_block(ast, enm, "FromBytes", true, None) } #[rustfmt::skip] @@ -165,7 +243,7 @@ const ENUM_FROM_BYTES_CFG: Config<EnumRepr> = { // - all fields are `FromBytes` fn derive_from_bytes_union(ast: &DeriveInput, unn: &DataUnion) -> proc_macro2::TokenStream { - impl_block(ast, unn, "FromBytes", true, PaddingCheck::None) + impl_block(ast, unn, "FromBytes", true, None) } // A struct is `AsBytes` if: @@ -175,16 +253,30 @@ fn derive_from_bytes_union(ast: &DeriveInput, unn: &DataUnion) -> proc_macro2::T // - `repr(packed)` fn derive_as_bytes_struct(ast: &DeriveInput, strct: &DataStruct) -> proc_macro2::TokenStream { - // TODO(#10): Support type parameters. - if !ast.generics.params.is_empty() { - return Error::new(Span::call_site(), "unsupported on types with type parameters") - .to_compile_error(); - } - let reprs = try_or_print!(STRUCT_UNION_AS_BYTES_CFG.validate_reprs(ast)); - let padding_check = - if reprs.contains(&StructRepr::Packed) { PaddingCheck::None } else { PaddingCheck::Struct }; + let is_transparent = reprs.contains(&StructRepr::Transparent); + let is_packed = reprs.contains(&StructRepr::Packed); + + // TODO(#10): Support type parameters for non-transparent, non-packed + // structs. + if !ast.generics.params.is_empty() && !is_transparent && !is_packed { + return Error::new( + Span::call_site(), + "unsupported on generic structs that are not repr(transparent) or repr(packed)", + ) + .to_compile_error(); + } + // We don't need a padding check if the struct is repr(transparent) or + // repr(packed). + // - repr(transparent): The layout and ABI of the whole struct is the same + // as its only non-ZST field (meaning there's no padding outside of that + // field) and we require that field to be `AsBytes` (meaning there's no + // padding in that field). + // - repr(packed): Any inter-field padding bytes are removed, meaning that + // any padding bytes would need to come from the fields, all of which + // we require to be `AsBytes` (meaning they don't have any padding). + let padding_check = if is_transparent || is_packed { None } else { Some(PaddingCheck::Struct) }; impl_block(ast, strct, "AsBytes", true, padding_check) } @@ -208,7 +300,7 @@ fn derive_as_bytes_enum(ast: &DeriveInput, enm: &DataEnum) -> proc_macro2::Token // We don't care what the repr is; we only care that it is one of the // allowed ones. let _: Vec<repr::EnumRepr> = try_or_print!(ENUM_AS_BYTES_CFG.validate_reprs(ast)); - impl_block(ast, enm, "AsBytes", false, PaddingCheck::None) + impl_block(ast, enm, "AsBytes", false, None) } #[rustfmt::skip] @@ -250,7 +342,7 @@ fn derive_as_bytes_union(ast: &DeriveInput, unn: &DataUnion) -> proc_macro2::Tok try_or_print!(STRUCT_UNION_AS_BYTES_CFG.validate_reprs(ast)); - impl_block(ast, unn, "AsBytes", true, PaddingCheck::Union) + impl_block(ast, unn, "AsBytes", true, Some(PaddingCheck::Union)) } // A struct is `Unaligned` if: @@ -263,7 +355,7 @@ fn derive_unaligned_struct(ast: &DeriveInput, strct: &DataStruct) -> proc_macro2 let reprs = try_or_print!(STRUCT_UNION_UNALIGNED_CFG.validate_reprs(ast)); let require_trait_bound = !reprs.contains(&StructRepr::Packed); - impl_block(ast, strct, "Unaligned", require_trait_bound, PaddingCheck::None) + impl_block(ast, strct, "Unaligned", require_trait_bound, None) } const STRUCT_UNION_UNALIGNED_CFG: Config<StructRepr> = Config { @@ -294,7 +386,7 @@ fn derive_unaligned_enum(ast: &DeriveInput, enm: &DataEnum) -> proc_macro2::Toke // for `require_trait_bounds` doesn't really do anything. But it's // marginally more future-proof in case that restriction is lifted in the // future. - impl_block(ast, enm, "Unaligned", true, PaddingCheck::None) + impl_block(ast, enm, "Unaligned", true, None) } #[rustfmt::skip] @@ -332,26 +424,37 @@ fn derive_unaligned_union(ast: &DeriveInput, unn: &DataUnion) -> proc_macro2::To let reprs = try_or_print!(STRUCT_UNION_UNALIGNED_CFG.validate_reprs(ast)); let require_trait_bound = !reprs.contains(&StructRepr::Packed); - impl_block(ast, unn, "Unaligned", require_trait_bound, PaddingCheck::None) + impl_block(ast, unn, "Unaligned", require_trait_bound, None) } // This enum describes what kind of padding check needs to be generated for the // associated impl. enum PaddingCheck { - // No additional padding check is required. - None, // Check that the sum of the fields' sizes exactly equals the struct's size. Struct, // Check that the size of each field exactly equals the union's size. Union, } +impl PaddingCheck { + /// Returns the ident of the macro to call in order to validate that a type + /// passes the padding check encoded by `PaddingCheck`. + fn validator_macro_ident(&self) -> Ident { + let s = match self { + PaddingCheck::Struct => "struct_has_padding", + PaddingCheck::Union => "union_has_padding", + }; + + Ident::new(s, Span::call_site()) + } +} + fn impl_block<D: DataExt>( input: &DeriveInput, data: &D, trait_name: &str, require_trait_bound: bool, - padding_check: PaddingCheck, + padding_check: Option<PaddingCheck>, ) -> proc_macro2::TokenStream { // In this documentation, we will refer to this hypothetical struct: // @@ -367,22 +470,10 @@ fn impl_block<D: DataExt>( // c: I::Item, // } // - // First, we extract the field types, which in this case are `u8`, `T`, and - // `I::Item`. We use the names of the type parameters to split the field - // types into two sets - a set of types which are based on the type - // parameters, and a set of types which are not. First, we re-use the - // existing parameters and where clauses, generating an `impl` block like: - // - // impl<T, I: Iterator> FromBytes for Foo<T, I> - // where - // T: Copy, - // I: Clone, - // I::Item: Clone, - // { - // } - // - // Then, we use the list of types which are based on the type parameters to - // generate new entries in the `where` clause: + // We extract the field types, which in this case are `u8`, `T`, and + // `I::Item`. We re-use the existing parameters and where clauses. If + // `require_trait_bound == true` (as it is for `FromBytes), we add where + // bounds for each field's type: // // impl<T, I: Iterator> FromBytes for Foo<T, I> // where @@ -394,18 +485,6 @@ fn impl_block<D: DataExt>( // { // } // - // Finally, we use a different technique to generate the bounds for the - // types which are not based on type parameters: - // - // - // fn only_derive_is_allowed_to_implement_this_trait() where Self: Sized { - // struct ImplementsFromBytes<F: ?Sized + FromBytes>(PhantomData<F>); - // let _: ImplementsFromBytes<u8>; - // } - // - // It would be easier to put all types in the where clause, but that won't - // work until the trivial_bounds feature is stabilized (#48214). - // // NOTE: It is standard practice to only emit bounds for the type parameters // themselves, not for field types based on those parameters (e.g., `T` vs // `T::Foo`). For a discussion of why this is standard practice, see @@ -416,31 +495,9 @@ fn impl_block<D: DataExt>( // `T::Foo: !FromBytes`. It would not be sound for us to accept a type with // a `T::Foo` field as `FromBytes` simply because `T: FromBytes`. // - // While there's no getting around this requirement for us, it does have - // some pretty serious downsides that are worth calling out: - // - // 1. You lose the ability to have fields of generic type with reduced visibility. - // - // #[derive(Unaligned)] - // #[repr(C)] - // pub struct Public<T>(Private<T>); - // - // #[derive(Unaligned)] - // #[repr(C)] - // struct Private<T>(T); - // - // - // warning: private type `Private<T>` in public interface (error E0446) - // --> src/main.rs:6:10 - // | - // 6 | #[derive(Unaligned)] - // | ^^^^^^^^^ - // | - // = note: #[warn(private_in_public)] on by default - // = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - // = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537> - // - // 2. When lifetimes are involved, the trait solver ties itself in knots. + // While there's no getting around this requirement for us, it does have the + // pretty serious downside that, when lifetimes are involved, the trait + // solver ties itself in knots: // // #[derive(Unaligned)] // #[repr(C)] @@ -449,7 +506,6 @@ fn impl_block<D: DataExt>( // b: PhantomData<&'b u8>, // } // - // // error[E0283]: type annotations required: cannot resolve `core::marker::PhantomData<&'a u8>: zerocopy::Unaligned` // --> src/main.rs:6:10 // | @@ -458,67 +514,37 @@ fn impl_block<D: DataExt>( // | // = note: required by `zerocopy::Unaligned` - // A visitor which is used to walk a field's type and determine whether any - // of its definition is based on the type or lifetime parameters on a type. - struct FromTypeParamVisit<'a, 'b>(&'a Punctuated<GenericParam, Comma>, &'b mut bool); - - impl<'a, 'b> Visit<'a> for FromTypeParamVisit<'a, 'b> { - fn visit_lifetime(&mut self, i: &'a Lifetime) { - visit::visit_lifetime(self, i); - if self.0.iter().any(|param| { - if let GenericParam::Lifetime(param) = param { - param.lifetime.ident == i.ident - } else { - false - } - }) { - *self.1 = true; - } - } - - fn visit_type_path(&mut self, i: &'a TypePath) { - visit::visit_type_path(self, i); - if self.0.iter().any(|param| { - if let GenericParam::Type(param) = param { - i.path.segments.first().unwrap().ident == param.ident - } else { - false - } - }) { - *self.1 = true; - } - } - } - - // Whether this type is based on one of the type parameters. E.g., given the - // type parameters `<T>`, `T`, `T::Foo`, and `(T::Foo, String)` are all - // based on the type parameters, while `String` and `(String, Box<()>)` are - // not. - let is_from_type_param = |ty: &Type| { - let mut ret = false; - FromTypeParamVisit(&input.generics.params, &mut ret).visit_type(ty); - ret - }; - + let type_ident = &input.ident; let trait_ident = Ident::new(trait_name, Span::call_site()); + let field_types = data.field_types(); + + let field_type_bounds = require_trait_bound + .then(|| field_types.iter().map(|ty| parse_quote!(#ty: zerocopy::#trait_ident))) + .into_iter() + .flatten() + .collect::<Vec<_>>(); + + // Don't bother emitting a padding check if there are no fields. + #[allow(unstable_name_collisions)] // See `BoolExt` below + let padding_check_bound = padding_check.and_then(|check| (!field_types.is_empty()).then_some(check)).map(|check| { + let fields = field_types.iter(); + let validator_macro = check.validator_macro_ident(); + parse_quote!( + zerocopy::derive_util::HasPadding<#type_ident, {zerocopy::#validator_macro!(#type_ident, #(#fields),*)}>: + zerocopy::derive_util::ShouldBe<false> + ) + }); - let field_types = data.nested_types(); - let type_param_field_types = field_types.iter().filter(|ty| is_from_type_param(ty)); - let non_type_param_field_types = field_types.iter().filter(|ty| !is_from_type_param(ty)); - - // Add a new set of where clause predicates of the form `T: Trait` for each - // of the types of the struct's fields (but only the ones whose types are - // based on one of the type parameters). - let mut generics = input.generics.clone(); - let where_clause = generics.make_where_clause(); - if require_trait_bound { - for ty in type_param_field_types { - let bound = parse_quote!(#ty: zerocopy::#trait_ident); - where_clause.predicates.push(bound); - } - } + let bounds = input + .generics + .where_clause + .as_ref() + .map(|where_clause| where_clause.predicates.iter()) + .into_iter() + .flatten() + .chain(field_type_bounds.iter()) + .chain(padding_check_bound.iter()); - let type_ident = &input.ident; // The parameters with trait bounds, but without type defaults. let params = input.generics.params.clone().into_iter().map(|mut param| { match &mut param { @@ -538,56 +564,12 @@ fn impl_block<D: DataExt>( GenericParam::Const(cnst) => quote!(#cnst), }); - let trait_bound_body = if require_trait_bound { - let implements_type_ident = - Ident::new(format!("Implements{}", trait_ident).as_str(), Span::call_site()); - let implements_type_tokens = quote!(#implements_type_ident); - let types = non_type_param_field_types.map(|ty| quote!(#implements_type_tokens<#ty>)); - quote!( - // A type with a type parameter that must implement `#trait_ident`. - struct #implements_type_ident<F: ?Sized + zerocopy::#trait_ident>(::core::marker::PhantomData<F>); - // For each field type, an instantiation that won't type check if - // that type doesn't implement `#trait_ident`. - #(let _: #types;)* - ) - } else { - quote!() - }; - - let size_check_body = match (field_types.is_empty(), padding_check) { - (true, _) | (false, PaddingCheck::None) => quote!(), - (false, PaddingCheck::Struct) => quote!( - const _: () = { - trait HasPadding<const HAS_PADDING: bool> {} - fn assert_no_padding<T: HasPadding<false>>() {} - - const COMPOSITE_TYPE_SIZE: usize = ::core::mem::size_of::<#type_ident>(); - const SUM_FIELD_SIZES: usize = 0 #(+ ::core::mem::size_of::<#field_types>())*; - const HAS_PADDING: bool = COMPOSITE_TYPE_SIZE > SUM_FIELD_SIZES; - impl HasPadding<HAS_PADDING> for #type_ident {} - let _ = assert_no_padding::<#type_ident>; - }; - ), - (false, PaddingCheck::Union) => quote!( - const _: () = { - trait FieldsAreSameSize<const FIELDS_ARE_SAME_SIZE: bool> {} - fn assert_fields_are_same_size<T: FieldsAreSameSize<true>>() {} - - const COMPOSITE_TYPE_SIZE: usize = ::core::mem::size_of::<#type_ident>(); - const FIELDS_ARE_SAME_SIZE: bool = true - #(&& (::core::mem::size_of::<#field_types>() == COMPOSITE_TYPE_SIZE))*; - impl FieldsAreSameSize<FIELDS_ARE_SAME_SIZE> for #type_ident {} - let _ = assert_fields_are_same_size::<#type_ident>; - }; - ), - }; - quote! { - unsafe impl < #(#params),* > zerocopy::#trait_ident for #type_ident < #(#param_idents),* > #where_clause { - fn only_derive_is_allowed_to_implement_this_trait() where Self: Sized { - #trait_bound_body - #size_check_body - } + unsafe impl < #(#params),* > zerocopy::#trait_ident for #type_ident < #(#param_idents),* > + where + #(#bounds,)* + { + fn only_derive_is_allowed_to_implement_this_trait() {} } } } @@ -596,6 +578,23 @@ fn print_all_errors(errors: Vec<Error>) -> proc_macro2::TokenStream { errors.iter().map(Error::to_compile_error).collect() } +// A polyfill for `Option::then_some`, which was added after our MSRV. +// +// TODO(#67): Remove this once our MSRV is >= 1.62. +trait BoolExt { + fn then_some<T>(self, t: T) -> Option<T>; +} + +impl BoolExt for bool { + fn then_some<T>(self, t: T) -> Option<T> { + if self { + Some(t) + } else { + None + } + } +} + #[cfg(test)] mod tests { use super::*; @@ -616,12 +615,12 @@ mod tests { } fn elements_are_sorted_and_deduped<T: Clone + Ord>(lists: &[&[T]]) -> bool { - lists.iter().all(|list| is_sorted_and_deduped(*list)) + lists.iter().all(|list| is_sorted_and_deduped(list)) } fn config_is_sorted<T: KindRepr + Clone>(config: &Config<T>) -> bool { - elements_are_sorted_and_deduped(&config.allowed_combinations) - && elements_are_sorted_and_deduped(&config.disallowed_but_legal_combinations) + elements_are_sorted_and_deduped(config.allowed_combinations) + && elements_are_sorted_and_deduped(config.disallowed_but_legal_combinations) } assert!(config_is_sorted(&STRUCT_UNION_UNALIGNED_CFG)); diff --git a/src/repr.rs b/src/repr.rs index 5bd4a8a..5997ad2 100644 --- a/src/repr.rs +++ b/src/repr.rs @@ -73,9 +73,7 @@ impl<R: KindRepr> Config<R> { } let initial_sp = metas[0].span(); - let err_span = metas.iter().skip(1).fold(Some(initial_sp), |sp_option, meta| { - sp_option.and_then(|sp| sp.join(meta.span())) - }); + let err_span = metas.iter().skip(1).try_fold(initial_sp, |sp, meta| sp.join(meta.span())); if self.allowed_combinations.contains(&reprs.as_slice()) { Ok(reprs) diff --git a/tests/enum_as_bytes.rs b/tests/enum_as_bytes.rs index be5c53d..e1b8efd 100644 --- a/tests/enum_as_bytes.rs +++ b/tests/enum_as_bytes.rs @@ -4,18 +4,7 @@ #![allow(warnings)] -use zerocopy::AsBytes; - -struct IsAsBytes<T: AsBytes>(T); - -// Fail compilation if `$ty: !AsBytes`. -macro_rules! is_as_bytes { - ($ty:ty) => { - const _: () = { - let _: IsAsBytes<$ty>; - }; - }; -} +use {static_assertions::assert_impl_all, zerocopy::AsBytes}; // An enum is `AsBytes` if if has a defined repr. @@ -25,7 +14,7 @@ enum C { A, } -is_as_bytes!(C); +assert_impl_all!(C: AsBytes); #[derive(AsBytes)] #[repr(u8)] @@ -33,7 +22,7 @@ enum U8 { A, } -is_as_bytes!(U8); +assert_impl_all!(U8: AsBytes); #[derive(AsBytes)] #[repr(u16)] @@ -41,7 +30,7 @@ enum U16 { A, } -is_as_bytes!(U16); +assert_impl_all!(U16: AsBytes); #[derive(AsBytes)] #[repr(u32)] @@ -49,7 +38,7 @@ enum U32 { A, } -is_as_bytes!(U32); +assert_impl_all!(U32: AsBytes); #[derive(AsBytes)] #[repr(u64)] @@ -57,7 +46,7 @@ enum U64 { A, } -is_as_bytes!(U64); +assert_impl_all!(U64: AsBytes); #[derive(AsBytes)] #[repr(usize)] @@ -65,7 +54,7 @@ enum Usize { A, } -is_as_bytes!(Usize); +assert_impl_all!(Usize: AsBytes); #[derive(AsBytes)] #[repr(i8)] @@ -73,7 +62,7 @@ enum I8 { A, } -is_as_bytes!(I8); +assert_impl_all!(I8: AsBytes); #[derive(AsBytes)] #[repr(i16)] @@ -81,7 +70,7 @@ enum I16 { A, } -is_as_bytes!(I16); +assert_impl_all!(I16: AsBytes); #[derive(AsBytes)] #[repr(i32)] @@ -89,7 +78,7 @@ enum I32 { A, } -is_as_bytes!(I32); +assert_impl_all!(I32: AsBytes); #[derive(AsBytes)] #[repr(i64)] @@ -97,7 +86,7 @@ enum I64 { A, } -is_as_bytes!(I64); +assert_impl_all!(I64: AsBytes); #[derive(AsBytes)] #[repr(isize)] @@ -105,4 +94,4 @@ enum Isize { A, } -is_as_bytes!(Isize); +assert_impl_all!(Isize: AsBytes); diff --git a/tests/enum_from_bytes.rs b/tests/enum_from_bytes.rs index 671878d..09fe847 100644 --- a/tests/enum_from_bytes.rs +++ b/tests/enum_from_bytes.rs @@ -4,7 +4,12 @@ #![allow(warnings)] -use zerocopy::FromBytes; +mod util; + +use { + static_assertions::assert_impl_all, + zerocopy::{FromBytes, FromZeroes}, +}; // An enum is `FromBytes` if: // - `repr(uN)` or `repr(iN)` @@ -23,18 +28,7 @@ use zerocopy::FromBytes; // `Variant128` has a discriminant of -128) since Rust won't automatically wrap // a signed discriminant around without you explicitly telling it to. -struct IsFromBytes<T: FromBytes>(T); - -// Fail compilation if `$ty: !FromBytes`. -macro_rules! is_from_bytes { - ($ty:ty) => { - const _: () = { - let _: IsFromBytes<$ty>; - }; - }; -} - -#[derive(FromBytes)] +#[derive(FromZeroes, FromBytes)] #[repr(u8)] enum FooU8 { Variant0, @@ -295,9 +289,9 @@ enum FooU8 { Variant255, } -is_from_bytes!(FooU8); +assert_impl_all!(FooU8: FromBytes); -#[derive(FromBytes)] +#[derive(FromZeroes, FromBytes)] #[repr(i8)] enum FooI8 { Variant0, @@ -558,9 +552,9 @@ enum FooI8 { Variant255, } -is_from_bytes!(FooI8); +assert_impl_all!(FooI8: FromBytes); -#[derive(FromBytes)] +#[derive(FromZeroes, FromBytes)] #[repr(u8, align(2))] enum FooU8Align { Variant0, @@ -821,9 +815,9 @@ enum FooU8Align { Variant255, } -is_from_bytes!(FooU8Align); +assert_impl_all!(FooU8Align: FromBytes); -#[derive(FromBytes)] +#[derive(FromZeroes, FromBytes)] #[repr(i8, align(2))] enum FooI8Align { Variant0, @@ -1084,9 +1078,9 @@ enum FooI8Align { Variant255, } -is_from_bytes!(FooI8Align); +assert_impl_all!(FooI8Align: FromBytes); -#[derive(FromBytes)] +#[derive(FromZeroes, FromBytes)] #[repr(u16)] enum FooU16 { Variant0, @@ -66627,9 +66621,9 @@ enum FooU16 { Variant65535, } -is_from_bytes!(FooU16); +assert_impl_all!(FooU16: FromBytes); -#[derive(FromBytes)] +#[derive(FromZeroes, FromBytes)] #[repr(i16)] enum FooI16 { Variant0, @@ -132170,4 +132164,4 @@ enum FooI16 { Variant65535, } -is_from_bytes!(FooI16); +assert_impl_all!(FooI16: FromBytes); diff --git a/tests/enum_from_zeroes.rs b/tests/enum_from_zeroes.rs new file mode 100644 index 0000000..3fedcb1 --- /dev/null +++ b/tests/enum_from_zeroes.rs @@ -0,0 +1,31 @@ +// Copyright 2022 The Fuchsia Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#![allow(warnings)] + +mod util; + +use {static_assertions::assert_impl_all, zerocopy::FromZeroes}; + +#[derive(FromZeroes)] +enum Foo { + A, +} + +assert_impl_all!(Foo: FromZeroes); + +#[derive(FromZeroes)] +enum Bar { + A = 0, +} + +assert_impl_all!(Bar: FromZeroes); + +#[derive(FromZeroes)] +enum Baz { + A = 1, + B = 0, +} + +assert_impl_all!(Baz: FromZeroes); diff --git a/tests/enum_unaligned.rs b/tests/enum_unaligned.rs index 5438135..1c7cb77 100644 --- a/tests/enum_unaligned.rs +++ b/tests/enum_unaligned.rs @@ -4,18 +4,7 @@ #![allow(warnings)] -use zerocopy::Unaligned; - -struct IsUnaligned<T: Unaligned>(T); - -// Fail compilation if `$ty: !Unaligned`. -macro_rules! is_unaligned { - ($ty:ty) => { - const _: () = { - let _: IsUnaligned<$ty>; - }; - }; -} +use {static_assertions::assert_impl_all, zerocopy::Unaligned}; // An enum is `Unaligned` if: // - No `repr(align(N > 1))` @@ -27,7 +16,7 @@ enum Foo { A, } -is_unaligned!(Foo); +assert_impl_all!(Foo: Unaligned); #[derive(Unaligned)] #[repr(i8)] @@ -35,7 +24,7 @@ enum Bar { A, } -is_unaligned!(Bar); +assert_impl_all!(Bar: Unaligned); #[derive(Unaligned)] #[repr(u8, align(1))] @@ -43,7 +32,7 @@ enum Baz { A, } -is_unaligned!(Baz); +assert_impl_all!(Baz: Unaligned); #[derive(Unaligned)] #[repr(i8, align(1))] @@ -51,4 +40,4 @@ enum Blah { B, } -is_unaligned!(Blah); +assert_impl_all!(Blah: Unaligned); diff --git a/tests/hygiene.rs b/tests/hygiene.rs index 42bbae9..9209bcd 100644 --- a/tests/hygiene.rs +++ b/tests/hygiene.rs @@ -9,11 +9,18 @@ extern crate zerocopy as _zerocopy; +#[macro_use] +mod util; + use std::{marker::PhantomData, option::IntoIter}; -use _zerocopy::FromBytes; +use { + _zerocopy::{FromBytes, FromZeroes, Unaligned}, + static_assertions::assert_impl_all, +}; -#[derive(FromBytes)] +#[derive(FromZeroes, FromBytes, Unaligned)] +#[repr(C)] struct TypeParams<'a, T, I: Iterator> { a: T, c: I::Item, @@ -23,8 +30,4 @@ struct TypeParams<'a, T, I: Iterator> { g: PhantomData<String>, } -const _FOO: () = { - let _: IsFromBytes<TypeParams<'static, (), IntoIter<()>>>; -}; - -struct IsFromBytes<T: FromBytes>(PhantomData<T>); +assert_impl_all!(TypeParams<'static, (), IntoIter<()>>: FromZeroes, FromBytes, Unaligned); diff --git a/tests/paths_and_modules.rs b/tests/paths_and_modules.rs index 065e8b2..8ca3aa2 100644 --- a/tests/paths_and_modules.rs +++ b/tests/paths_and_modules.rs @@ -4,19 +4,21 @@ #![allow(warnings)] -use zerocopy::FromBytes; +use zerocopy::{AsBytes, FromBytes, FromZeroes, Unaligned}; // Ensure that types that are use'd and types that are referenced by path work. mod foo { - use zerocopy::FromBytes; + use zerocopy::{AsBytes, FromBytes, FromZeroes, Unaligned}; - #[derive(FromBytes)] + #[derive(FromZeroes, FromBytes, AsBytes, Unaligned)] + #[repr(C)] pub struct Foo { foo: u8, } - #[derive(FromBytes)] + #[derive(FromZeroes, FromBytes, AsBytes, Unaligned)] + #[repr(C)] pub struct Bar { bar: u8, } @@ -24,7 +26,8 @@ mod foo { use foo::Foo; -#[derive(FromBytes)] +#[derive(FromZeroes, FromBytes, AsBytes, Unaligned)] +#[repr(C)] struct Baz { foo: Foo, bar: foo::Bar, diff --git a/tests/priv_in_pub.rs b/tests/priv_in_pub.rs new file mode 100644 index 0000000..f61568a --- /dev/null +++ b/tests/priv_in_pub.rs @@ -0,0 +1,20 @@ +// Copyright 2019 The Fuchsia Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +use zerocopy::{AsBytes, FromBytes, FromZeroes, Unaligned}; + +// These derives do not result in E0446 as of Rust 1.59.0, because of +// https://github.com/rust-lang/rust/pull/90586. +// +// This change eliminates one of the major downsides of emitting `where` +// bounds for field types (i.e., the emission of E0446 for private field +// types). + +#[derive(AsBytes, FromZeroes, FromBytes, Unaligned)] +#[repr(C)] +pub struct Public(Private); + +#[derive(AsBytes, FromZeroes, FromBytes, Unaligned)] +#[repr(C)] +struct Private(()); diff --git a/tests/struct_as_bytes.rs b/tests/struct_as_bytes.rs index fd464ce..e1507aa 100644 --- a/tests/struct_as_bytes.rs +++ b/tests/struct_as_bytes.rs @@ -4,20 +4,13 @@ #![allow(warnings)] -use std::{marker::PhantomData, option::IntoIter}; +mod util; -use zerocopy::AsBytes; +use std::{marker::PhantomData, mem::ManuallyDrop, option::IntoIter}; -struct IsAsBytes<T: AsBytes>(T); +use {static_assertions::assert_impl_all, zerocopy::AsBytes}; -// Fail compilation if `$ty: !AsBytes`. -macro_rules! is_as_bytes { - ($ty:ty) => { - const _: () = { - let _: IsAsBytes<$ty>; - }; - }; -} +use self::util::AU16; // A struct is `AsBytes` if: // - all fields are `AsBytes` @@ -29,17 +22,17 @@ macro_rules! is_as_bytes { #[repr(C)] struct CZst; -is_as_bytes!(CZst); +assert_impl_all!(CZst: AsBytes); #[derive(AsBytes)] #[repr(C)] struct C { a: u8, b: u8, - c: u16, + c: AU16, } -is_as_bytes!(C); +assert_impl_all!(C: AsBytes); #[derive(AsBytes)] #[repr(transparent)] @@ -48,19 +41,90 @@ struct Transparent { b: CZst, } -is_as_bytes!(Transparent); +assert_impl_all!(Transparent: AsBytes); + +#[derive(AsBytes)] +#[repr(transparent)] +struct TransparentGeneric<T: ?Sized> { + a: CZst, + b: T, +} + +assert_impl_all!(TransparentGeneric<u64>: AsBytes); +assert_impl_all!(TransparentGeneric<[u64]>: AsBytes); #[derive(AsBytes)] #[repr(C, packed)] struct CZstPacked; -is_as_bytes!(CZstPacked); +assert_impl_all!(CZstPacked: AsBytes); #[derive(AsBytes)] #[repr(C, packed)] struct CPacked { a: u8, + // NOTE: The `u16` type is not guaranteed to have alignment 2, although it + // does on many platforms. However, to fix this would require a custom type + // with a `#[repr(align(2))]` attribute, and `#[repr(packed)]` types are not + // allowed to transitively contain `#[repr(align(...))]` types. Thus, we + // have no choice but to use `u16` here. Luckily, these tests run in CI on + // platforms on which `u16` has alignment 2, so this isn't that big of a + // deal. + b: u16, +} + +assert_impl_all!(CPacked: AsBytes); + +#[derive(AsBytes)] +#[repr(C, packed)] +struct CPackedGeneric<T, U: ?Sized> { + t: T, + // Unsized types stored in `repr(packed)` structs must not be dropped + // because dropping them in-place might be unsound depending on the + // alignment of the outer struct. Sized types can be dropped by first being + // moved to an aligned stack variable, but this isn't possible with unsized + // types. + u: ManuallyDrop<U>, +} + +assert_impl_all!(CPackedGeneric<u8, AU16>: AsBytes); +assert_impl_all!(CPackedGeneric<u8, [AU16]>: AsBytes); + +#[derive(AsBytes)] +#[repr(packed)] +struct Packed { + a: u8, + // NOTE: The `u16` type is not guaranteed to have alignment 2, although it + // does on many platforms. However, to fix this would require a custom type + // with a `#[repr(align(2))]` attribute, and `#[repr(packed)]` types are not + // allowed to transitively contain `#[repr(align(...))]` types. Thus, we + // have no choice but to use `u16` here. Luckily, these tests run in CI on + // platforms on which `u16` has alignment 2, so this isn't that big of a + // deal. b: u16, } -is_as_bytes!(CPacked); +assert_impl_all!(Packed: AsBytes); + +#[derive(AsBytes)] +#[repr(packed)] +struct PackedGeneric<T, U: ?Sized> { + t: T, + // Unsized types stored in `repr(packed)` structs must not be dropped + // because dropping them in-place might be unsound depending on the + // alignment of the outer struct. Sized types can be dropped by first being + // moved to an aligned stack variable, but this isn't possible with unsized + // types. + u: ManuallyDrop<U>, +} + +assert_impl_all!(PackedGeneric<u8, AU16>: AsBytes); +assert_impl_all!(PackedGeneric<u8, [AU16]>: AsBytes); + +#[derive(AsBytes)] +#[repr(transparent)] +struct Unsized { + a: [u8], +} + +assert_impl_all!(Unsized: AsBytes); diff --git a/tests/struct_from_bytes.rs b/tests/struct_from_bytes.rs index 7ebc300..5dc68d2 100644 --- a/tests/struct_from_bytes.rs +++ b/tests/struct_from_bytes.rs @@ -4,52 +4,57 @@ #![allow(warnings)] -use std::{marker::PhantomData, option::IntoIter}; +mod util; -use zerocopy::FromBytes; +use std::{marker::PhantomData, option::IntoIter}; -struct IsFromBytes<T: FromBytes>(T); +use { + static_assertions::assert_impl_all, + zerocopy::{FromBytes, FromZeroes}, +}; -// Fail compilation if `$ty: !FromBytes`. -macro_rules! is_from_bytes { - ($ty:ty) => { - const _: () = { - let _: IsFromBytes<$ty>; - }; - }; -} +use crate::util::AU16; // A struct is `FromBytes` if: // - all fields are `FromBytes` -#[derive(FromBytes)] +#[derive(FromZeroes, FromBytes)] struct Zst; -is_from_bytes!(Zst); +assert_impl_all!(Zst: FromBytes); -#[derive(FromBytes)] +#[derive(FromZeroes, FromBytes)] struct One { a: u8, } -is_from_bytes!(One); +assert_impl_all!(One: FromBytes); -#[derive(FromBytes)] +#[derive(FromZeroes, FromBytes)] struct Two { a: u8, b: Zst, } -is_from_bytes!(Two); +assert_impl_all!(Two: FromBytes); + +#[derive(FromZeroes, FromBytes)] +struct Unsized { + a: [u8], +} + +assert_impl_all!(Unsized: FromBytes); -#[derive(FromBytes)] -struct TypeParams<'a, T, I: Iterator> { - a: T, - c: I::Item, - d: u8, - e: PhantomData<&'a [u8]>, - f: PhantomData<&'static str>, - g: PhantomData<String>, +#[derive(FromZeroes, FromBytes)] +struct TypeParams<'a, T: ?Sized, I: Iterator> { + a: I::Item, + b: u8, + c: PhantomData<&'a [u8]>, + d: PhantomData<&'static str>, + e: PhantomData<String>, + f: T, } -is_from_bytes!(TypeParams<'static, (), IntoIter<()>>); +assert_impl_all!(TypeParams<'static, (), IntoIter<()>>: FromBytes); +assert_impl_all!(TypeParams<'static, AU16, IntoIter<()>>: FromBytes); +assert_impl_all!(TypeParams<'static, [AU16], IntoIter<()>>: FromBytes); diff --git a/tests/struct_from_zeroes.rs b/tests/struct_from_zeroes.rs new file mode 100644 index 0000000..e9609d1 --- /dev/null +++ b/tests/struct_from_zeroes.rs @@ -0,0 +1,58 @@ +// Copyright 2022 The Fuchsia Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#![allow(warnings)] + +#[macro_use] +mod util; + +use std::{marker::PhantomData, option::IntoIter}; + +use {static_assertions::assert_impl_all, zerocopy::FromZeroes}; + +use crate::util::AU16; + +// A struct is `FromZeroes` if: +// - all fields are `FromZeroes` + +#[derive(FromZeroes)] +struct Zst; + +assert_impl_all!(Zst: FromZeroes); + +#[derive(FromZeroes)] +struct One { + a: bool, +} + +assert_impl_all!(One: FromZeroes); + +#[derive(FromZeroes)] +struct Two { + a: bool, + b: Zst, +} + +assert_impl_all!(Two: FromZeroes); + +#[derive(FromZeroes)] +struct Unsized { + a: [u8], +} + +assert_impl_all!(Unsized: FromZeroes); + +#[derive(FromZeroes)] +struct TypeParams<'a, T: ?Sized, I: Iterator> { + a: I::Item, + b: u8, + c: PhantomData<&'a [u8]>, + d: PhantomData<&'static str>, + e: PhantomData<String>, + f: T, +} + +assert_impl_all!(TypeParams<'static, (), IntoIter<()>>: FromZeroes); +assert_impl_all!(TypeParams<'static, AU16, IntoIter<()>>: FromZeroes); +assert_impl_all!(TypeParams<'static, [AU16], IntoIter<()>>: FromZeroes); diff --git a/tests/struct_unaligned.rs b/tests/struct_unaligned.rs index 355c208..e843a0c 100644 --- a/tests/struct_unaligned.rs +++ b/tests/struct_unaligned.rs @@ -4,20 +4,13 @@ #![allow(warnings)] -use std::{marker::PhantomData, option::IntoIter}; +mod util; -use zerocopy::Unaligned; +use std::{marker::PhantomData, option::IntoIter}; -struct IsUnaligned<T: Unaligned>(T); +use {static_assertions::assert_impl_all, zerocopy::Unaligned}; -// Fail compilation if `$ty: !Unaligned`. -macro_rules! is_unaligned { - ($ty:ty) => { - const _: () = { - let _: IsUnaligned<$ty>; - }; - }; -} +use crate::util::AU16; // A struct is `Unaligned` if: // - `repr(align)` is no more than 1 and either @@ -31,7 +24,7 @@ struct Foo { a: u8, } -is_unaligned!(Foo); +assert_impl_all!(Foo: Unaligned); #[derive(Unaligned)] #[repr(transparent)] @@ -39,15 +32,22 @@ struct Bar { a: u8, } -is_unaligned!(Bar); +assert_impl_all!(Bar: Unaligned); #[derive(Unaligned)] #[repr(packed)] struct Baz { + // NOTE: The `u16` type is not guaranteed to have alignment 2, although it + // does on many platforms. However, to fix this would require a custom type + // with a `#[repr(align(2))]` attribute, and `#[repr(packed)]` types are not + // allowed to transitively contain `#[repr(align(...))]` types. Thus, we + // have no choice but to use `u16` here. Luckily, these tests run in CI on + // platforms on which `u16` has alignment 2, so this isn't that big of a + // deal. a: u16, } -is_unaligned!(Baz); +assert_impl_all!(Baz: Unaligned); #[derive(Unaligned)] #[repr(C, align(1))] @@ -55,17 +55,27 @@ struct FooAlign { a: u8, } -is_unaligned!(FooAlign); +assert_impl_all!(FooAlign: Unaligned); + +#[derive(Unaligned)] +#[repr(transparent)] +struct Unsized { + a: [u8], +} + +assert_impl_all!(Unsized: Unaligned); #[derive(Unaligned)] #[repr(C)] -struct TypeParams<'a, T, I: Iterator> { - a: T, - c: I::Item, - d: u8, - e: PhantomData<&'a [u8]>, - f: PhantomData<&'static str>, - g: PhantomData<String>, +struct TypeParams<'a, T: ?Sized, I: Iterator> { + a: I::Item, + b: u8, + c: PhantomData<&'a [u8]>, + d: PhantomData<&'static str>, + e: PhantomData<String>, + f: T, } -is_unaligned!(TypeParams<'static, (), IntoIter<()>>); +assert_impl_all!(TypeParams<'static, (), IntoIter<()>>: Unaligned); +assert_impl_all!(TypeParams<'static, u8, IntoIter<()>>: Unaligned); +assert_impl_all!(TypeParams<'static, [u8], IntoIter<()>>: Unaligned); diff --git a/tests/trybuild.rs b/tests/trybuild.rs index b95a716..32f38cc 100644 --- a/tests/trybuild.rs +++ b/tests/trybuild.rs @@ -8,18 +8,18 @@ // pin to specific versions in CI (a specific stable version, a specific date of // the nightly compiler, and a specific MSRV). Updating those pinned versions // may also require updating these tests. -// - `tests/ui` - Contains the source of truth for our UI test source files -// (`.rs`), and contains `.err` and `.out` files for nightly and beta -// - `tests/ui-stable` - Contains symlinks to the `.rs` files in `tests/ui`, and -// contains `.err` and `.out` files for stable -// - `tests/ui-msrv` - Contains symlinks to the `.rs` files in `tests/ui`, and -// contains `.err` and `.out` files for MSRV +// - `tests/ui-nightly` - Contains the source of truth for our UI test source +// files (`.rs`), and contains `.err` and `.out` files for nightly +// - `tests/ui-stable` - Contains symlinks to the `.rs` files in +// `tests/ui-nightly`, and contains `.err` and `.out` files for stable +// - `tests/ui-msrv` - Contains symlinks to the `.rs` files in +// `tests/ui-nightly`, and contains `.err` and `.out` files for MSRV -#[rustversion::any(nightly, beta)] -const SOURCE_FILES_GLOB: &str = "tests/ui/*.rs"; -#[rustversion::all(stable, not(stable(1.56.1)))] +#[rustversion::nightly] +const SOURCE_FILES_GLOB: &str = "tests/ui-nightly/*.rs"; +#[rustversion::stable(1.69.0)] const SOURCE_FILES_GLOB: &str = "tests/ui-stable/*.rs"; -#[rustversion::stable(1.56.1)] +#[rustversion::stable(1.61.0)] const SOURCE_FILES_GLOB: &str = "tests/ui-msrv/*.rs"; #[test] diff --git a/tests/ui-msrv/derive_transparent.rs b/tests/ui-msrv/derive_transparent.rs new file mode 100644 index 0000000..a99f92c --- /dev/null +++ b/tests/ui-msrv/derive_transparent.rs @@ -0,0 +1,36 @@ +// Copyright 2019 The Fuchsia Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +extern crate zerocopy; + +#[path = "../util.rs"] +mod util; + +use core::marker::PhantomData; + +use { + static_assertions::assert_impl_all, + zerocopy::{AsBytes, FromBytes, FromZeroes, Unaligned}, +}; + +use self::util::NotZerocopy; + +fn main() {} + +// Test generic transparent structs + +#[derive(AsBytes, FromZeroes, FromBytes, Unaligned)] +#[repr(transparent)] +struct TransparentStruct<T> { + inner: T, + _phantom: PhantomData<()>, +} + +// It should be legal to derive these traits on a transparent struct, but it +// must also ensure the traits are only implemented when the inner type +// implements them. +assert_impl_all!(TransparentStruct<NotZerocopy>: FromZeroes); +assert_impl_all!(TransparentStruct<NotZerocopy>: FromBytes); +assert_impl_all!(TransparentStruct<NotZerocopy>: AsBytes); +assert_impl_all!(TransparentStruct<NotZerocopy>: Unaligned); diff --git a/tests/ui-msrv/derive_transparent.stderr b/tests/ui-msrv/derive_transparent.stderr new file mode 100644 index 0000000..3218446 --- /dev/null +++ b/tests/ui-msrv/derive_transparent.stderr @@ -0,0 +1,71 @@ +error[E0277]: the trait bound `NotZerocopy: FromZeroes` is not satisfied + --> tests/ui-msrv/derive_transparent.rs:33:1 + | +33 | assert_impl_all!(TransparentStruct<NotZerocopy>: FromZeroes); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromZeroes` is not implemented for `NotZerocopy` + | +note: required because of the requirements on the impl of `FromZeroes` for `TransparentStruct<NotZerocopy>` + --> tests/ui-msrv/derive_transparent.rs:23:19 + | +23 | #[derive(AsBytes, FromZeroes, FromBytes, Unaligned)] + | ^^^^^^^^^^ +note: required by a bound in `_::{closure#0}::assert_impl_all` + --> tests/ui-msrv/derive_transparent.rs:33:1 + | +33 | assert_impl_all!(TransparentStruct<NotZerocopy>: FromZeroes); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `_::{closure#0}::assert_impl_all` + = note: this error originates in the macro `assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: FromBytes` is not satisfied + --> tests/ui-msrv/derive_transparent.rs:34:1 + | +34 | assert_impl_all!(TransparentStruct<NotZerocopy>: FromBytes); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromBytes` is not implemented for `NotZerocopy` + | +note: required because of the requirements on the impl of `FromBytes` for `TransparentStruct<NotZerocopy>` + --> tests/ui-msrv/derive_transparent.rs:23:31 + | +23 | #[derive(AsBytes, FromZeroes, FromBytes, Unaligned)] + | ^^^^^^^^^ +note: required by a bound in `_::{closure#0}::assert_impl_all` + --> tests/ui-msrv/derive_transparent.rs:34:1 + | +34 | assert_impl_all!(TransparentStruct<NotZerocopy>: FromBytes); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `_::{closure#0}::assert_impl_all` + = note: this error originates in the macro `assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: AsBytes` is not satisfied + --> tests/ui-msrv/derive_transparent.rs:35:1 + | +35 | assert_impl_all!(TransparentStruct<NotZerocopy>: AsBytes); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsBytes` is not implemented for `NotZerocopy` + | +note: required because of the requirements on the impl of `AsBytes` for `TransparentStruct<NotZerocopy>` + --> tests/ui-msrv/derive_transparent.rs:23:10 + | +23 | #[derive(AsBytes, FromZeroes, FromBytes, Unaligned)] + | ^^^^^^^ +note: required by a bound in `_::{closure#0}::assert_impl_all` + --> tests/ui-msrv/derive_transparent.rs:35:1 + | +35 | assert_impl_all!(TransparentStruct<NotZerocopy>: AsBytes); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `_::{closure#0}::assert_impl_all` + = note: this error originates in the macro `assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: Unaligned` is not satisfied + --> tests/ui-msrv/derive_transparent.rs:36:1 + | +36 | assert_impl_all!(TransparentStruct<NotZerocopy>: Unaligned); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Unaligned` is not implemented for `NotZerocopy` + | +note: required because of the requirements on the impl of `Unaligned` for `TransparentStruct<NotZerocopy>` + --> tests/ui-msrv/derive_transparent.rs:23:42 + | +23 | #[derive(AsBytes, FromZeroes, FromBytes, Unaligned)] + | ^^^^^^^^^ +note: required by a bound in `_::{closure#0}::assert_impl_all` + --> tests/ui-msrv/derive_transparent.rs:36:1 + | +36 | assert_impl_all!(TransparentStruct<NotZerocopy>: Unaligned); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `_::{closure#0}::assert_impl_all` + = note: this error originates in the macro `assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-msrv/enum.rs b/tests/ui-msrv/enum.rs index 188b0a6..c3d1e27 100644 --- a/tests/ui-msrv/enum.rs +++ b/tests/ui-msrv/enum.rs @@ -11,76 +11,97 @@ fn main() {} // Generic errors // -#[derive(FromBytes)] +#[derive(FromZeroes, FromBytes)] #[repr("foo")] enum Generic1 { A, } -#[derive(FromBytes)] +#[derive(FromZeroes, FromBytes)] #[repr(foo)] enum Generic2 { A, } -#[derive(FromBytes)] +#[derive(FromZeroes, FromBytes)] #[repr(transparent)] enum Generic3 { A, } -#[derive(FromBytes)] +#[derive(FromZeroes, FromBytes)] #[repr(u8, u16)] enum Generic4 { A, } -#[derive(FromBytes)] +#[derive(FromZeroes, FromBytes)] enum Generic5 { A, } // +// FromZeroes errors +// + +#[derive(FromZeroes)] +enum FromZeroes1 { + A(u8), +} + +#[derive(FromZeroes)] +enum FromZeroes2 { + A, + B(u8), +} + +#[derive(FromZeroes)] +enum FromZeroes3 { + A = 1, + B, +} + +// // FromBytes errors // -#[derive(FromBytes)] +#[derive(FromZeroes, FromBytes)] #[repr(C)] enum FromBytes1 { A, } -#[derive(FromBytes)] +#[derive(FromZeroes, FromBytes)] #[repr(usize)] enum FromBytes2 { A, } -#[derive(FromBytes)] +#[derive(FromZeroes, FromBytes)] #[repr(isize)] enum FromBytes3 { A, } -#[derive(FromBytes)] +#[derive(FromZeroes, FromBytes)] #[repr(u32)] enum FromBytes4 { A, } -#[derive(FromBytes)] +#[derive(FromZeroes, FromBytes)] #[repr(i32)] enum FromBytes5 { A, } -#[derive(FromBytes)] +#[derive(FromZeroes, FromBytes)] #[repr(u64)] enum FromBytes6 { A, } -#[derive(FromBytes)] +#[derive(FromZeroes, FromBytes)] #[repr(i64)] enum FromBytes7 { A, diff --git a/tests/ui-msrv/enum.stderr b/tests/ui-msrv/enum.stderr index 14ddb0b..a71b072 100644 --- a/tests/ui-msrv/enum.stderr +++ b/tests/ui-msrv/enum.stderr @@ -23,131 +23,157 @@ error: conflicting representation hints | ^ error: must have a non-align #[repr(...)] attribute in order to guarantee this type's memory layout - --> tests/ui-msrv/enum.rs:38:10 + --> tests/ui-msrv/enum.rs:38:22 | -38 | #[derive(FromBytes)] - | ^^^^^^^^^ +38 | #[derive(FromZeroes, FromBytes)] + | ^^^^^^^^^ | = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) +error: only C-like enums can implement FromZeroes + --> tests/ui-msrv/enum.rs:48:1 + | +48 | / enum FromZeroes1 { +49 | | A(u8), +50 | | } + | |_^ + +error: only C-like enums can implement FromZeroes + --> tests/ui-msrv/enum.rs:53:1 + | +53 | / enum FromZeroes2 { +54 | | A, +55 | | B(u8), +56 | | } + | |_^ + +error: FromZeroes only supported on enums with a variant that has a discriminant of `0` + --> tests/ui-msrv/enum.rs:59:1 + | +59 | / enum FromZeroes3 { +60 | | A = 1, +61 | | B, +62 | | } + | |_^ + error: FromBytes requires repr of "u8", "u16", "i8", or "i16" - --> tests/ui-msrv/enum.rs:48:8 + --> tests/ui-msrv/enum.rs:69:8 | -48 | #[repr(C)] +69 | #[repr(C)] | ^ error: FromBytes requires repr of "u8", "u16", "i8", or "i16" - --> tests/ui-msrv/enum.rs:54:8 + --> tests/ui-msrv/enum.rs:75:8 | -54 | #[repr(usize)] +75 | #[repr(usize)] | ^^^^^ error: FromBytes requires repr of "u8", "u16", "i8", or "i16" - --> tests/ui-msrv/enum.rs:60:8 + --> tests/ui-msrv/enum.rs:81:8 | -60 | #[repr(isize)] +81 | #[repr(isize)] | ^^^^^ error: FromBytes requires repr of "u8", "u16", "i8", or "i16" - --> tests/ui-msrv/enum.rs:66:8 + --> tests/ui-msrv/enum.rs:87:8 | -66 | #[repr(u32)] +87 | #[repr(u32)] | ^^^ error: FromBytes requires repr of "u8", "u16", "i8", or "i16" - --> tests/ui-msrv/enum.rs:72:8 + --> tests/ui-msrv/enum.rs:93:8 | -72 | #[repr(i32)] +93 | #[repr(i32)] | ^^^ error: FromBytes requires repr of "u8", "u16", "i8", or "i16" - --> tests/ui-msrv/enum.rs:78:8 + --> tests/ui-msrv/enum.rs:99:8 | -78 | #[repr(u64)] +99 | #[repr(u64)] | ^^^ error: FromBytes requires repr of "u8", "u16", "i8", or "i16" - --> tests/ui-msrv/enum.rs:84:8 - | -84 | #[repr(i64)] - | ^^^ + --> tests/ui-msrv/enum.rs:105:8 + | +105 | #[repr(i64)] + | ^^^ error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1))) - --> tests/ui-msrv/enum.rs:94:8 - | -94 | #[repr(C)] - | ^ + --> tests/ui-msrv/enum.rs:115:8 + | +115 | #[repr(C)] + | ^ error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1))) - --> tests/ui-msrv/enum.rs:100:8 + --> tests/ui-msrv/enum.rs:121:8 | -100 | #[repr(u16)] +121 | #[repr(u16)] | ^^^ error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1))) - --> tests/ui-msrv/enum.rs:106:8 + --> tests/ui-msrv/enum.rs:127:8 | -106 | #[repr(i16)] +127 | #[repr(i16)] | ^^^ error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1))) - --> tests/ui-msrv/enum.rs:112:8 + --> tests/ui-msrv/enum.rs:133:8 | -112 | #[repr(u32)] +133 | #[repr(u32)] | ^^^ error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1))) - --> tests/ui-msrv/enum.rs:118:8 + --> tests/ui-msrv/enum.rs:139:8 | -118 | #[repr(i32)] +139 | #[repr(i32)] | ^^^ error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1))) - --> tests/ui-msrv/enum.rs:124:8 + --> tests/ui-msrv/enum.rs:145:8 | -124 | #[repr(u64)] +145 | #[repr(u64)] | ^^^ error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1))) - --> tests/ui-msrv/enum.rs:130:8 + --> tests/ui-msrv/enum.rs:151:8 | -130 | #[repr(i64)] +151 | #[repr(i64)] | ^^^ error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1))) - --> tests/ui-msrv/enum.rs:136:8 + --> tests/ui-msrv/enum.rs:157:8 | -136 | #[repr(usize)] +157 | #[repr(usize)] | ^^^^^ error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1))) - --> tests/ui-msrv/enum.rs:142:8 + --> tests/ui-msrv/enum.rs:163:8 | -142 | #[repr(isize)] +163 | #[repr(isize)] | ^^^^^ error: cannot derive Unaligned with repr(align(N > 1)) - --> tests/ui-msrv/enum.rs:148:12 + --> tests/ui-msrv/enum.rs:169:12 | -148 | #[repr(u8, align(2))] +169 | #[repr(u8, align(2))] | ^^^^^^^^ error: cannot derive Unaligned with repr(align(N > 1)) - --> tests/ui-msrv/enum.rs:154:12 + --> tests/ui-msrv/enum.rs:175:12 | -154 | #[repr(i8, align(2))] +175 | #[repr(i8, align(2))] | ^^^^^^^^ error: cannot derive Unaligned with repr(align(N > 1)) - --> tests/ui-msrv/enum.rs:160:18 + --> tests/ui-msrv/enum.rs:181:18 | -160 | #[repr(align(1), align(2))] +181 | #[repr(align(1), align(2))] | ^^^^^^^^ error: cannot derive Unaligned with repr(align(N > 1)) - --> tests/ui-msrv/enum.rs:166:8 + --> tests/ui-msrv/enum.rs:187:8 | -166 | #[repr(align(2), align(4))] +187 | #[repr(align(2), align(4))] | ^^^^^^^^ error[E0565]: meta item in `repr` must be an identifier diff --git a/tests/ui-msrv/late_compile_pass.rs b/tests/ui-msrv/late_compile_pass.rs index 3a99c76..1b4c603 100644 --- a/tests/ui-msrv/late_compile_pass.rs +++ b/tests/ui-msrv/late_compile_pass.rs @@ -5,6 +5,11 @@ #[macro_use] extern crate zerocopy; +#[path = "../util.rs"] +mod util; + +use self::util::{NotZerocopy, AU16}; + fn main() {} // These tests cause errors which are generated by a later compilation pass than @@ -12,12 +17,21 @@ fn main() {} // the compiler will never get to that pass, and so we won't get the errors. // +// FromZeroes errors +// + +#[derive(FromZeroes)] +struct FromZeroes1 { + value: NotZerocopy, +} + +// // FromBytes errors // #[derive(FromBytes)] struct FromBytes1 { - not_from_bytes: &'static str, + value: NotZerocopy, } // @@ -27,8 +41,7 @@ struct FromBytes1 { #[derive(AsBytes)] #[repr(C)] struct AsBytes1 { - a: u8, - b: u16, + value: NotZerocopy, } // @@ -38,7 +51,7 @@ struct AsBytes1 { #[derive(Unaligned)] #[repr(C)] struct Unaligned1 { - aligned: u16, + aligned: AU16, } // This specifically tests a bug we had in an old version of the code in which @@ -47,11 +60,11 @@ struct Unaligned1 { #[repr(C)] struct Unaligned2 { unaligned: u8, - aligned: u16, + aligned: AU16, } #[derive(Unaligned)] #[repr(transparent)] struct Unaligned3 { - aligned: u16, + aligned: AU16, } diff --git a/tests/ui-msrv/late_compile_pass.stderr b/tests/ui-msrv/late_compile_pass.stderr index a692474..29d20e4 100644 --- a/tests/ui-msrv/late_compile_pass.stderr +++ b/tests/ui-msrv/late_compile_pass.stderr @@ -1,66 +1,66 @@ -error[E0277]: the trait bound `AsBytes1: HasPadding<false>` is not satisfied - --> tests/ui-msrv/late_compile_pass.rs:27:10 +error[E0277]: the trait bound `NotZerocopy: FromZeroes` is not satisfied + --> tests/ui-msrv/late_compile_pass.rs:23:10 | -27 | #[derive(AsBytes)] - | ^^^^^^^ the trait `HasPadding<false>` is not implemented for `AsBytes1` +23 | #[derive(FromZeroes)] + | ^^^^^^^^^^ the trait `FromZeroes` is not implemented for `NotZerocopy` | - = help: the following implementations were found: - <AsBytes1 as HasPadding<true>> -note: required by a bound in `assert_no_padding` - --> tests/ui-msrv/late_compile_pass.rs:27:10 + = help: see issue #48214 + = note: this error originates in the derive macro `FromZeroes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: FromBytes` is not satisfied + --> tests/ui-msrv/late_compile_pass.rs:32:10 | -27 | #[derive(AsBytes)] - | ^^^^^^^ required by this bound in `assert_no_padding` - = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info) +32 | #[derive(FromBytes)] + | ^^^^^^^^^ the trait `FromBytes` is not implemented for `NotZerocopy` + | + = help: see issue #48214 + = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0277]: the trait bound `&'static str: FromBytes` is not satisfied - --> tests/ui-msrv/late_compile_pass.rs:18:10 +error[E0277]: the trait bound `FromBytes1: FromZeroes` is not satisfied + --> tests/ui-msrv/late_compile_pass.rs:32:10 | -18 | #[derive(FromBytes)] - | ^^^^^^^^^ the trait `FromBytes` is not implemented for `&'static str` +32 | #[derive(FromBytes)] + | ^^^^^^^^^ the trait `FromZeroes` is not implemented for `FromBytes1` | -note: required by a bound in `ImplementsFromBytes` - --> tests/ui-msrv/late_compile_pass.rs:18:10 +note: required by a bound in `FromBytes` + --> $WORKSPACE/src/lib.rs | -18 | #[derive(FromBytes)] - | ^^^^^^^^^ required by this bound in `ImplementsFromBytes` + | pub unsafe trait FromBytes: FromZeroes { + | ^^^^^^^^^^ required by this bound in `FromBytes` = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0277]: the trait bound `u16: Unaligned` is not satisfied - --> tests/ui-msrv/late_compile_pass.rs:38:10 +error[E0277]: the trait bound `NotZerocopy: AsBytes` is not satisfied + --> tests/ui-msrv/late_compile_pass.rs:41:10 | -38 | #[derive(Unaligned)] - | ^^^^^^^^^ the trait `Unaligned` is not implemented for `u16` +41 | #[derive(AsBytes)] + | ^^^^^^^ the trait `AsBytes` is not implemented for `NotZerocopy` | -note: required by a bound in `<Unaligned1 as Unaligned>::only_derive_is_allowed_to_implement_this_trait::ImplementsUnaligned` - --> tests/ui-msrv/late_compile_pass.rs:38:10 + = help: see issue #48214 + = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `AU16: Unaligned` is not satisfied + --> tests/ui-msrv/late_compile_pass.rs:51:10 + | +51 | #[derive(Unaligned)] + | ^^^^^^^^^ the trait `Unaligned` is not implemented for `AU16` | -38 | #[derive(Unaligned)] - | ^^^^^^^^^ required by this bound in `<Unaligned1 as Unaligned>::only_derive_is_allowed_to_implement_this_trait::ImplementsUnaligned` + = help: see issue #48214 = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0277]: the trait bound `u16: Unaligned` is not satisfied - --> tests/ui-msrv/late_compile_pass.rs:46:10 +error[E0277]: the trait bound `AU16: Unaligned` is not satisfied + --> tests/ui-msrv/late_compile_pass.rs:59:10 | -46 | #[derive(Unaligned)] - | ^^^^^^^^^ the trait `Unaligned` is not implemented for `u16` +59 | #[derive(Unaligned)] + | ^^^^^^^^^ the trait `Unaligned` is not implemented for `AU16` | -note: required by a bound in `<Unaligned2 as Unaligned>::only_derive_is_allowed_to_implement_this_trait::ImplementsUnaligned` - --> tests/ui-msrv/late_compile_pass.rs:46:10 - | -46 | #[derive(Unaligned)] - | ^^^^^^^^^ required by this bound in `<Unaligned2 as Unaligned>::only_derive_is_allowed_to_implement_this_trait::ImplementsUnaligned` + = help: see issue #48214 = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0277]: the trait bound `u16: Unaligned` is not satisfied - --> tests/ui-msrv/late_compile_pass.rs:53:10 - | -53 | #[derive(Unaligned)] - | ^^^^^^^^^ the trait `Unaligned` is not implemented for `u16` +error[E0277]: the trait bound `AU16: Unaligned` is not satisfied + --> tests/ui-msrv/late_compile_pass.rs:66:10 | -note: required by a bound in `<Unaligned3 as Unaligned>::only_derive_is_allowed_to_implement_this_trait::ImplementsUnaligned` - --> tests/ui-msrv/late_compile_pass.rs:53:10 +66 | #[derive(Unaligned)] + | ^^^^^^^^^ the trait `Unaligned` is not implemented for `AU16` | -53 | #[derive(Unaligned)] - | ^^^^^^^^^ required by this bound in `<Unaligned3 as Unaligned>::only_derive_is_allowed_to_implement_this_trait::ImplementsUnaligned` + = help: see issue #48214 = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-msrv/struct.rs b/tests/ui-msrv/struct.rs index ee8fd06..29aa0e8 100644 --- a/tests/ui-msrv/struct.rs +++ b/tests/ui-msrv/struct.rs @@ -5,6 +5,11 @@ #[macro_use] extern crate zerocopy; +#[path = "../util.rs"] +mod util; + +use self::util::AU16; + fn main() {} // @@ -15,6 +20,13 @@ fn main() {} #[repr(C)] struct AsBytes1<T>(T); +#[derive(AsBytes)] +#[repr(C)] +struct AsBytes2 { + foo: u8, + bar: AU16, +} + // // Unaligned errors // diff --git a/tests/ui-msrv/struct.stderr b/tests/ui-msrv/struct.stderr index c3e91d4..fe73b80 100644 --- a/tests/ui-msrv/struct.stderr +++ b/tests/ui-msrv/struct.stderr @@ -1,49 +1,54 @@ -error: unsupported on types with type parameters - --> tests/ui-msrv/struct.rs:14:10 +error: unsupported on generic structs that are not repr(transparent) or repr(packed) + --> tests/ui-msrv/struct.rs:19:10 | -14 | #[derive(AsBytes)] +19 | #[derive(AsBytes)] | ^^^^^^^ | = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info) error: cannot derive Unaligned with repr(align(N > 1)) - --> tests/ui-msrv/struct.rs:23:11 + --> tests/ui-msrv/struct.rs:35:11 | -23 | #[repr(C, align(2))] +35 | #[repr(C, align(2))] | ^^^^^^^^ error: cannot derive Unaligned with repr(align(N > 1)) - --> tests/ui-msrv/struct.rs:27:21 + --> tests/ui-msrv/struct.rs:39:21 | -27 | #[repr(transparent, align(2))] +39 | #[repr(transparent, align(2))] | ^^^^^^^^ error: cannot derive Unaligned with repr(align(N > 1)) - --> tests/ui-msrv/struct.rs:33:16 + --> tests/ui-msrv/struct.rs:45:16 | -33 | #[repr(packed, align(2))] +45 | #[repr(packed, align(2))] | ^^^^^^^^ error: cannot derive Unaligned with repr(align(N > 1)) - --> tests/ui-msrv/struct.rs:37:18 + --> tests/ui-msrv/struct.rs:49:18 | -37 | #[repr(align(1), align(2))] +49 | #[repr(align(1), align(2))] | ^^^^^^^^ error: cannot derive Unaligned with repr(align(N > 1)) - --> tests/ui-msrv/struct.rs:41:8 + --> tests/ui-msrv/struct.rs:53:8 | -41 | #[repr(align(2), align(4))] +53 | #[repr(align(2), align(4))] | ^^^^^^^^ error[E0692]: transparent struct cannot have other repr hints - --> tests/ui-msrv/struct.rs:27:8 + --> tests/ui-msrv/struct.rs:39:8 | -27 | #[repr(transparent, align(2))] +39 | #[repr(transparent, align(2))] | ^^^^^^^^^^^ ^^^^^^^^ -error[E0587]: type has conflicting packed and align representation hints - --> tests/ui-msrv/struct.rs:34:1 +error[E0277]: the trait bound `HasPadding<AsBytes2, true>: ShouldBe<false>` is not satisfied + --> tests/ui-msrv/struct.rs:23:10 | -34 | struct Unaligned3; - | ^^^^^^^^^^^^^^^^^^ +23 | #[derive(AsBytes)] + | ^^^^^^^ the trait `ShouldBe<false>` is not implemented for `HasPadding<AsBytes2, true>` + | + = help: the following implementations were found: + <HasPadding<T, VALUE> as ShouldBe<VALUE>> + = help: see issue #48214 + = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-msrv/union.rs b/tests/ui-msrv/union.rs index 0252cbe..e7761e0 100644 --- a/tests/ui-msrv/union.rs +++ b/tests/ui-msrv/union.rs @@ -5,6 +5,10 @@ #[macro_use] extern crate zerocopy; +#[path = "../util.rs"] +mod util; + +use self::util::AU16; use std::mem::ManuallyDrop; fn main() {} @@ -21,7 +25,7 @@ union AsBytes1<T> { #[derive(AsBytes)] #[repr(C)] -union AsBytes { +union AsBytes2 { foo: u8, bar: [u8; 2], } @@ -34,7 +38,7 @@ union AsBytes { #[repr(C, align(2))] union Unaligned1 { foo: i16, - bar: u16, + bar: AU16, } // Transparent unions are unstable; see issue #60405 diff --git a/tests/ui-msrv/union.stderr b/tests/ui-msrv/union.stderr index 56b72be..711b8e2 100644 --- a/tests/ui-msrv/union.stderr +++ b/tests/ui-msrv/union.stderr @@ -1,54 +1,42 @@ error: unsupported on types with type parameters - --> tests/ui-msrv/union.rs:16:10 + --> tests/ui-msrv/union.rs:20:10 | -16 | #[derive(AsBytes)] +20 | #[derive(AsBytes)] | ^^^^^^^ | = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info) error: cannot derive Unaligned with repr(align(N > 1)) - --> tests/ui-msrv/union.rs:34:11 + --> tests/ui-msrv/union.rs:38:11 | -34 | #[repr(C, align(2))] +38 | #[repr(C, align(2))] | ^^^^^^^^ error: cannot derive Unaligned with repr(align(N > 1)) - --> tests/ui-msrv/union.rs:50:16 + --> tests/ui-msrv/union.rs:54:16 | -50 | #[repr(packed, align(2))] +54 | #[repr(packed, align(2))] | ^^^^^^^^ error: cannot derive Unaligned with repr(align(N > 1)) - --> tests/ui-msrv/union.rs:56:18 + --> tests/ui-msrv/union.rs:60:18 | -56 | #[repr(align(1), align(2))] +60 | #[repr(align(1), align(2))] | ^^^^^^^^ error: cannot derive Unaligned with repr(align(N > 1)) - --> tests/ui-msrv/union.rs:62:8 + --> tests/ui-msrv/union.rs:66:8 | -62 | #[repr(align(2), align(4))] +66 | #[repr(align(2), align(4))] | ^^^^^^^^ -error[E0277]: the trait bound `AsBytes: FieldsAreSameSize<true>` is not satisfied - --> tests/ui-msrv/union.rs:22:10 +error[E0277]: the trait bound `HasPadding<AsBytes2, true>: ShouldBe<false>` is not satisfied + --> tests/ui-msrv/union.rs:26:10 | -22 | #[derive(AsBytes)] - | ^^^^^^^ the trait `FieldsAreSameSize<true>` is not implemented for `AsBytes` +26 | #[derive(AsBytes)] + | ^^^^^^^ the trait `ShouldBe<false>` is not implemented for `HasPadding<AsBytes2, true>` | = help: the following implementations were found: - <AsBytes as FieldsAreSameSize<false>> -note: required by a bound in `assert_fields_are_same_size` - --> tests/ui-msrv/union.rs:22:10 - | -22 | #[derive(AsBytes)] - | ^^^^^^^ required by this bound in `assert_fields_are_same_size` + <HasPadding<T, VALUE> as ShouldBe<VALUE>> + = help: see issue #48214 = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info) - -error[E0587]: type has conflicting packed and align representation hints - --> tests/ui-msrv/union.rs:51:1 - | -51 | / union Unaligned3 { -52 | | foo: u8, -53 | | } - | |_^ diff --git a/tests/ui-nightly/derive_transparent.rs b/tests/ui-nightly/derive_transparent.rs new file mode 100644 index 0000000..a99f92c --- /dev/null +++ b/tests/ui-nightly/derive_transparent.rs @@ -0,0 +1,36 @@ +// Copyright 2019 The Fuchsia Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +extern crate zerocopy; + +#[path = "../util.rs"] +mod util; + +use core::marker::PhantomData; + +use { + static_assertions::assert_impl_all, + zerocopy::{AsBytes, FromBytes, FromZeroes, Unaligned}, +}; + +use self::util::NotZerocopy; + +fn main() {} + +// Test generic transparent structs + +#[derive(AsBytes, FromZeroes, FromBytes, Unaligned)] +#[repr(transparent)] +struct TransparentStruct<T> { + inner: T, + _phantom: PhantomData<()>, +} + +// It should be legal to derive these traits on a transparent struct, but it +// must also ensure the traits are only implemented when the inner type +// implements them. +assert_impl_all!(TransparentStruct<NotZerocopy>: FromZeroes); +assert_impl_all!(TransparentStruct<NotZerocopy>: FromBytes); +assert_impl_all!(TransparentStruct<NotZerocopy>: AsBytes); +assert_impl_all!(TransparentStruct<NotZerocopy>: Unaligned); diff --git a/tests/ui-nightly/derive_transparent.stderr b/tests/ui-nightly/derive_transparent.stderr new file mode 100644 index 0000000..5a7d507 --- /dev/null +++ b/tests/ui-nightly/derive_transparent.stderr @@ -0,0 +1,111 @@ +error[E0277]: the trait bound `NotZerocopy: FromZeroes` is not satisfied + --> tests/ui-nightly/derive_transparent.rs:33:18 + | +33 | assert_impl_all!(TransparentStruct<NotZerocopy>: FromZeroes); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromZeroes` is not implemented for `NotZerocopy` + | + = help: the following other types implement trait `FromZeroes`: + () + AU16 + F32<O> + F64<O> + I128<O> + I16<O> + I32<O> + I64<O> + and $N others +note: required for `TransparentStruct<NotZerocopy>` to implement `FromZeroes` + --> tests/ui-nightly/derive_transparent.rs:23:19 + | +23 | #[derive(AsBytes, FromZeroes, FromBytes, Unaligned)] + | ^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +note: required by a bound in `_::{closure#0}::assert_impl_all` + --> tests/ui-nightly/derive_transparent.rs:33:1 + | +33 | assert_impl_all!(TransparentStruct<NotZerocopy>: FromZeroes); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `assert_impl_all` + = note: this error originates in the derive macro `FromZeroes` which comes from the expansion of the macro `assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: FromBytes` is not satisfied + --> tests/ui-nightly/derive_transparent.rs:34:18 + | +34 | assert_impl_all!(TransparentStruct<NotZerocopy>: FromBytes); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromBytes` is not implemented for `NotZerocopy` + | + = help: the following other types implement trait `FromBytes`: + () + AU16 + F32<O> + F64<O> + I128<O> + I16<O> + I32<O> + I64<O> + and $N others +note: required for `TransparentStruct<NotZerocopy>` to implement `FromBytes` + --> tests/ui-nightly/derive_transparent.rs:23:31 + | +23 | #[derive(AsBytes, FromZeroes, FromBytes, Unaligned)] + | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +note: required by a bound in `_::{closure#0}::assert_impl_all` + --> tests/ui-nightly/derive_transparent.rs:34:1 + | +34 | assert_impl_all!(TransparentStruct<NotZerocopy>: FromBytes); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `assert_impl_all` + = note: this error originates in the derive macro `FromBytes` which comes from the expansion of the macro `assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: AsBytes` is not satisfied + --> tests/ui-nightly/derive_transparent.rs:35:18 + | +35 | assert_impl_all!(TransparentStruct<NotZerocopy>: AsBytes); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsBytes` is not implemented for `NotZerocopy` + | + = help: the following other types implement trait `AsBytes`: + () + AU16 + F32<O> + F64<O> + I128<O> + I16<O> + I32<O> + I64<O> + and $N others +note: required for `TransparentStruct<NotZerocopy>` to implement `AsBytes` + --> tests/ui-nightly/derive_transparent.rs:23:10 + | +23 | #[derive(AsBytes, FromZeroes, FromBytes, Unaligned)] + | ^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +note: required by a bound in `_::{closure#0}::assert_impl_all` + --> tests/ui-nightly/derive_transparent.rs:35:1 + | +35 | assert_impl_all!(TransparentStruct<NotZerocopy>: AsBytes); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `assert_impl_all` + = note: this error originates in the derive macro `AsBytes` which comes from the expansion of the macro `assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: Unaligned` is not satisfied + --> tests/ui-nightly/derive_transparent.rs:36:18 + | +36 | assert_impl_all!(TransparentStruct<NotZerocopy>: Unaligned); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Unaligned` is not implemented for `NotZerocopy` + | + = help: the following other types implement trait `Unaligned`: + () + F32<O> + F64<O> + I128<O> + I16<O> + I32<O> + I64<O> + ManuallyDrop<T> + and $N others +note: required for `TransparentStruct<NotZerocopy>` to implement `Unaligned` + --> tests/ui-nightly/derive_transparent.rs:23:42 + | +23 | #[derive(AsBytes, FromZeroes, FromBytes, Unaligned)] + | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +note: required by a bound in `_::{closure#0}::assert_impl_all` + --> tests/ui-nightly/derive_transparent.rs:36:1 + | +36 | assert_impl_all!(TransparentStruct<NotZerocopy>: Unaligned); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `assert_impl_all` + = note: this error originates in the derive macro `Unaligned` which comes from the expansion of the macro `assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/enum.rs b/tests/ui-nightly/enum.rs index 188b0a6..c3d1e27 100644 --- a/tests/ui/enum.rs +++ b/tests/ui-nightly/enum.rs @@ -11,76 +11,97 @@ fn main() {} // Generic errors // -#[derive(FromBytes)] +#[derive(FromZeroes, FromBytes)] #[repr("foo")] enum Generic1 { A, } -#[derive(FromBytes)] +#[derive(FromZeroes, FromBytes)] #[repr(foo)] enum Generic2 { A, } -#[derive(FromBytes)] +#[derive(FromZeroes, FromBytes)] #[repr(transparent)] enum Generic3 { A, } -#[derive(FromBytes)] +#[derive(FromZeroes, FromBytes)] #[repr(u8, u16)] enum Generic4 { A, } -#[derive(FromBytes)] +#[derive(FromZeroes, FromBytes)] enum Generic5 { A, } // +// FromZeroes errors +// + +#[derive(FromZeroes)] +enum FromZeroes1 { + A(u8), +} + +#[derive(FromZeroes)] +enum FromZeroes2 { + A, + B(u8), +} + +#[derive(FromZeroes)] +enum FromZeroes3 { + A = 1, + B, +} + +// // FromBytes errors // -#[derive(FromBytes)] +#[derive(FromZeroes, FromBytes)] #[repr(C)] enum FromBytes1 { A, } -#[derive(FromBytes)] +#[derive(FromZeroes, FromBytes)] #[repr(usize)] enum FromBytes2 { A, } -#[derive(FromBytes)] +#[derive(FromZeroes, FromBytes)] #[repr(isize)] enum FromBytes3 { A, } -#[derive(FromBytes)] +#[derive(FromZeroes, FromBytes)] #[repr(u32)] enum FromBytes4 { A, } -#[derive(FromBytes)] +#[derive(FromZeroes, FromBytes)] #[repr(i32)] enum FromBytes5 { A, } -#[derive(FromBytes)] +#[derive(FromZeroes, FromBytes)] #[repr(u64)] enum FromBytes6 { A, } -#[derive(FromBytes)] +#[derive(FromZeroes, FromBytes)] #[repr(i64)] enum FromBytes7 { A, diff --git a/tests/ui/enum.stderr b/tests/ui-nightly/enum.stderr index eeaee34..0c291b5 100644 --- a/tests/ui/enum.stderr +++ b/tests/ui-nightly/enum.stderr @@ -1,163 +1,189 @@ error: unrecognized representation hint - --> tests/ui/enum.rs:15:8 + --> tests/ui-nightly/enum.rs:15:8 | 15 | #[repr("foo")] | ^^^^^ error: unrecognized representation hint - --> tests/ui/enum.rs:21:8 + --> tests/ui-nightly/enum.rs:21:8 | 21 | #[repr(foo)] | ^^^ error: unsupported representation for deriving FromBytes, AsBytes, or Unaligned on an enum - --> tests/ui/enum.rs:27:8 + --> tests/ui-nightly/enum.rs:27:8 | 27 | #[repr(transparent)] | ^^^^^^^^^^^ error: conflicting representation hints - --> tests/ui/enum.rs:33:8 + --> tests/ui-nightly/enum.rs:33:8 | 33 | #[repr(u8, u16)] | ^^^^^^^ error: must have a non-align #[repr(...)] attribute in order to guarantee this type's memory layout - --> tests/ui/enum.rs:38:10 + --> tests/ui-nightly/enum.rs:38:22 | -38 | #[derive(FromBytes)] - | ^^^^^^^^^ +38 | #[derive(FromZeroes, FromBytes)] + | ^^^^^^^^^ | = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) +error: only C-like enums can implement FromZeroes + --> tests/ui-nightly/enum.rs:48:1 + | +48 | / enum FromZeroes1 { +49 | | A(u8), +50 | | } + | |_^ + +error: only C-like enums can implement FromZeroes + --> tests/ui-nightly/enum.rs:53:1 + | +53 | / enum FromZeroes2 { +54 | | A, +55 | | B(u8), +56 | | } + | |_^ + +error: FromZeroes only supported on enums with a variant that has a discriminant of `0` + --> tests/ui-nightly/enum.rs:59:1 + | +59 | / enum FromZeroes3 { +60 | | A = 1, +61 | | B, +62 | | } + | |_^ + error: FromBytes requires repr of "u8", "u16", "i8", or "i16" - --> tests/ui/enum.rs:48:8 + --> tests/ui-nightly/enum.rs:69:8 | -48 | #[repr(C)] +69 | #[repr(C)] | ^ error: FromBytes requires repr of "u8", "u16", "i8", or "i16" - --> tests/ui/enum.rs:54:8 + --> tests/ui-nightly/enum.rs:75:8 | -54 | #[repr(usize)] +75 | #[repr(usize)] | ^^^^^ error: FromBytes requires repr of "u8", "u16", "i8", or "i16" - --> tests/ui/enum.rs:60:8 + --> tests/ui-nightly/enum.rs:81:8 | -60 | #[repr(isize)] +81 | #[repr(isize)] | ^^^^^ error: FromBytes requires repr of "u8", "u16", "i8", or "i16" - --> tests/ui/enum.rs:66:8 + --> tests/ui-nightly/enum.rs:87:8 | -66 | #[repr(u32)] +87 | #[repr(u32)] | ^^^ error: FromBytes requires repr of "u8", "u16", "i8", or "i16" - --> tests/ui/enum.rs:72:8 + --> tests/ui-nightly/enum.rs:93:8 | -72 | #[repr(i32)] +93 | #[repr(i32)] | ^^^ error: FromBytes requires repr of "u8", "u16", "i8", or "i16" - --> tests/ui/enum.rs:78:8 + --> tests/ui-nightly/enum.rs:99:8 | -78 | #[repr(u64)] +99 | #[repr(u64)] | ^^^ error: FromBytes requires repr of "u8", "u16", "i8", or "i16" - --> tests/ui/enum.rs:84:8 - | -84 | #[repr(i64)] - | ^^^ + --> tests/ui-nightly/enum.rs:105:8 + | +105 | #[repr(i64)] + | ^^^ error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1))) - --> tests/ui/enum.rs:94:8 - | -94 | #[repr(C)] - | ^ + --> tests/ui-nightly/enum.rs:115:8 + | +115 | #[repr(C)] + | ^ error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1))) - --> tests/ui/enum.rs:100:8 + --> tests/ui-nightly/enum.rs:121:8 | -100 | #[repr(u16)] +121 | #[repr(u16)] | ^^^ error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1))) - --> tests/ui/enum.rs:106:8 + --> tests/ui-nightly/enum.rs:127:8 | -106 | #[repr(i16)] +127 | #[repr(i16)] | ^^^ error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1))) - --> tests/ui/enum.rs:112:8 + --> tests/ui-nightly/enum.rs:133:8 | -112 | #[repr(u32)] +133 | #[repr(u32)] | ^^^ error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1))) - --> tests/ui/enum.rs:118:8 + --> tests/ui-nightly/enum.rs:139:8 | -118 | #[repr(i32)] +139 | #[repr(i32)] | ^^^ error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1))) - --> tests/ui/enum.rs:124:8 + --> tests/ui-nightly/enum.rs:145:8 | -124 | #[repr(u64)] +145 | #[repr(u64)] | ^^^ error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1))) - --> tests/ui/enum.rs:130:8 + --> tests/ui-nightly/enum.rs:151:8 | -130 | #[repr(i64)] +151 | #[repr(i64)] | ^^^ error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1))) - --> tests/ui/enum.rs:136:8 + --> tests/ui-nightly/enum.rs:157:8 | -136 | #[repr(usize)] +157 | #[repr(usize)] | ^^^^^ error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1))) - --> tests/ui/enum.rs:142:8 + --> tests/ui-nightly/enum.rs:163:8 | -142 | #[repr(isize)] +163 | #[repr(isize)] | ^^^^^ error: cannot derive Unaligned with repr(align(N > 1)) - --> tests/ui/enum.rs:148:12 + --> tests/ui-nightly/enum.rs:169:12 | -148 | #[repr(u8, align(2))] +169 | #[repr(u8, align(2))] | ^^^^^^^^ error: cannot derive Unaligned with repr(align(N > 1)) - --> tests/ui/enum.rs:154:12 + --> tests/ui-nightly/enum.rs:175:12 | -154 | #[repr(i8, align(2))] +175 | #[repr(i8, align(2))] | ^^^^^^^^ error: cannot derive Unaligned with repr(align(N > 1)) - --> tests/ui/enum.rs:160:18 + --> tests/ui-nightly/enum.rs:181:18 | -160 | #[repr(align(1), align(2))] +181 | #[repr(align(1), align(2))] | ^^^^^^^^ error: cannot derive Unaligned with repr(align(N > 1)) - --> tests/ui/enum.rs:166:8 + --> tests/ui-nightly/enum.rs:187:8 | -166 | #[repr(align(2), align(4))] +187 | #[repr(align(2), align(4))] | ^^^^^^^^ error[E0565]: meta item in `repr` must be an identifier - --> tests/ui/enum.rs:15:8 + --> tests/ui-nightly/enum.rs:15:8 | 15 | #[repr("foo")] | ^^^^^ error[E0552]: unrecognized representation hint - --> tests/ui/enum.rs:21:8 + --> tests/ui-nightly/enum.rs:21:8 | 21 | #[repr(foo)] | ^^^ @@ -165,11 +191,11 @@ error[E0552]: unrecognized representation hint = help: valid reprs are `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` error[E0566]: conflicting representation hints - --> tests/ui/enum.rs:33:8 + --> tests/ui-nightly/enum.rs:33:8 | 33 | #[repr(u8, u16)] | ^^ ^^^ | - = note: `#[deny(conflicting_repr_hints)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #68585 <https://github.com/rust-lang/rust/issues/68585> + = note: `#[deny(conflicting_repr_hints)]` on by default diff --git a/tests/ui/enum_from_bytes_u16_too_few.rs.disabled b/tests/ui-nightly/enum_from_bytes_u16_too_few.rs.disabled index 99bc764..99bc764 100644 --- a/tests/ui/enum_from_bytes_u16_too_few.rs.disabled +++ b/tests/ui-nightly/enum_from_bytes_u16_too_few.rs.disabled diff --git a/tests/ui/enum_from_bytes_u8_too_few.rs b/tests/ui-nightly/enum_from_bytes_u8_too_few.rs index 4f54ec7..4f54ec7 100644 --- a/tests/ui/enum_from_bytes_u8_too_few.rs +++ b/tests/ui-nightly/enum_from_bytes_u8_too_few.rs diff --git a/tests/ui/enum_from_bytes_u8_too_few.stderr b/tests/ui-nightly/enum_from_bytes_u8_too_few.stderr index b75f6c2..1ecba21 100644 --- a/tests/ui/enum_from_bytes_u8_too_few.stderr +++ b/tests/ui-nightly/enum_from_bytes_u8_too_few.stderr @@ -1,5 +1,5 @@ error: FromBytes only supported on repr(u8) enum with 256 variants - --> tests/ui/enum_from_bytes_u8_too_few.rs:11:1 + --> tests/ui-nightly/enum_from_bytes_u8_too_few.rs:11:1 | 11 | / #[repr(u8)] 12 | | enum Foo { diff --git a/tests/ui/late_compile_pass.rs b/tests/ui-nightly/late_compile_pass.rs index 3a99c76..1b4c603 100644 --- a/tests/ui/late_compile_pass.rs +++ b/tests/ui-nightly/late_compile_pass.rs @@ -5,6 +5,11 @@ #[macro_use] extern crate zerocopy; +#[path = "../util.rs"] +mod util; + +use self::util::{NotZerocopy, AU16}; + fn main() {} // These tests cause errors which are generated by a later compilation pass than @@ -12,12 +17,21 @@ fn main() {} // the compiler will never get to that pass, and so we won't get the errors. // +// FromZeroes errors +// + +#[derive(FromZeroes)] +struct FromZeroes1 { + value: NotZerocopy, +} + +// // FromBytes errors // #[derive(FromBytes)] struct FromBytes1 { - not_from_bytes: &'static str, + value: NotZerocopy, } // @@ -27,8 +41,7 @@ struct FromBytes1 { #[derive(AsBytes)] #[repr(C)] struct AsBytes1 { - a: u8, - b: u16, + value: NotZerocopy, } // @@ -38,7 +51,7 @@ struct AsBytes1 { #[derive(Unaligned)] #[repr(C)] struct Unaligned1 { - aligned: u16, + aligned: AU16, } // This specifically tests a bug we had in an old version of the code in which @@ -47,11 +60,11 @@ struct Unaligned1 { #[repr(C)] struct Unaligned2 { unaligned: u8, - aligned: u16, + aligned: AU16, } #[derive(Unaligned)] #[repr(transparent)] struct Unaligned3 { - aligned: u16, + aligned: AU16, } diff --git a/tests/ui-nightly/late_compile_pass.stderr b/tests/ui-nightly/late_compile_pass.stderr new file mode 100644 index 0000000..fbf9da7 --- /dev/null +++ b/tests/ui-nightly/late_compile_pass.stderr @@ -0,0 +1,142 @@ +error[E0277]: the trait bound `NotZerocopy: FromZeroes` is not satisfied + --> tests/ui-nightly/late_compile_pass.rs:23:10 + | +23 | #[derive(FromZeroes)] + | ^^^^^^^^^^ the trait `FromZeroes` is not implemented for `NotZerocopy` + | + = help: the following other types implement trait `FromZeroes`: + () + AU16 + F32<O> + F64<O> + FromZeroes1 + I128<O> + I16<O> + I32<O> + and $N others + = help: see issue #48214 + = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + = note: this error originates in the derive macro `FromZeroes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: FromBytes` is not satisfied + --> tests/ui-nightly/late_compile_pass.rs:32:10 + | +32 | #[derive(FromBytes)] + | ^^^^^^^^^ the trait `FromBytes` is not implemented for `NotZerocopy` + | + = help: the following other types implement trait `FromBytes`: + () + AU16 + F32<O> + F64<O> + FromBytes1 + I128<O> + I16<O> + I32<O> + and $N others + = help: see issue #48214 + = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `FromBytes1: FromZeroes` is not satisfied + --> tests/ui-nightly/late_compile_pass.rs:32:10 + | +32 | #[derive(FromBytes)] + | ^^^^^^^^^ the trait `FromZeroes` is not implemented for `FromBytes1` + | + = help: the following other types implement trait `FromZeroes`: + () + AU16 + F32<O> + F64<O> + FromZeroes1 + I128<O> + I16<O> + I32<O> + and $N others +note: required by a bound in `FromBytes` + --> $WORKSPACE/src/lib.rs + | + | pub unsafe trait FromBytes: FromZeroes { + | ^^^^^^^^^^ required by this bound in `FromBytes` + = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: AsBytes` is not satisfied + --> tests/ui-nightly/late_compile_pass.rs:41:10 + | +41 | #[derive(AsBytes)] + | ^^^^^^^ the trait `AsBytes` is not implemented for `NotZerocopy` + | + = help: the following other types implement trait `AsBytes`: + () + AU16 + AsBytes1 + F32<O> + F64<O> + I128<O> + I16<O> + I32<O> + and $N others + = help: see issue #48214 + = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `AU16: Unaligned` is not satisfied + --> tests/ui-nightly/late_compile_pass.rs:51:10 + | +51 | #[derive(Unaligned)] + | ^^^^^^^^^ the trait `Unaligned` is not implemented for `AU16` + | + = help: the following other types implement trait `Unaligned`: + () + F32<O> + F64<O> + I128<O> + I16<O> + I32<O> + I64<O> + ManuallyDrop<T> + and $N others + = help: see issue #48214 + = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `AU16: Unaligned` is not satisfied + --> tests/ui-nightly/late_compile_pass.rs:59:10 + | +59 | #[derive(Unaligned)] + | ^^^^^^^^^ the trait `Unaligned` is not implemented for `AU16` + | + = help: the following other types implement trait `Unaligned`: + () + F32<O> + F64<O> + I128<O> + I16<O> + I32<O> + I64<O> + ManuallyDrop<T> + and $N others + = help: see issue #48214 + = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `AU16: Unaligned` is not satisfied + --> tests/ui-nightly/late_compile_pass.rs:66:10 + | +66 | #[derive(Unaligned)] + | ^^^^^^^^^ the trait `Unaligned` is not implemented for `AU16` + | + = help: the following other types implement trait `Unaligned`: + () + F32<O> + F64<O> + I128<O> + I16<O> + I32<O> + I64<O> + ManuallyDrop<T> + and $N others + = help: see issue #48214 + = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/struct.rs b/tests/ui-nightly/struct.rs index ee8fd06..29aa0e8 100644 --- a/tests/ui/struct.rs +++ b/tests/ui-nightly/struct.rs @@ -5,6 +5,11 @@ #[macro_use] extern crate zerocopy; +#[path = "../util.rs"] +mod util; + +use self::util::AU16; + fn main() {} // @@ -15,6 +20,13 @@ fn main() {} #[repr(C)] struct AsBytes1<T>(T); +#[derive(AsBytes)] +#[repr(C)] +struct AsBytes2 { + foo: u8, + bar: AU16, +} + // // Unaligned errors // diff --git a/tests/ui-nightly/struct.stderr b/tests/ui-nightly/struct.stderr new file mode 100644 index 0000000..a75d070 --- /dev/null +++ b/tests/ui-nightly/struct.stderr @@ -0,0 +1,54 @@ +error: unsupported on generic structs that are not repr(transparent) or repr(packed) + --> tests/ui-nightly/struct.rs:19:10 + | +19 | #[derive(AsBytes)] + | ^^^^^^^ + | + = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: cannot derive Unaligned with repr(align(N > 1)) + --> tests/ui-nightly/struct.rs:35:11 + | +35 | #[repr(C, align(2))] + | ^^^^^^^^ + +error: cannot derive Unaligned with repr(align(N > 1)) + --> tests/ui-nightly/struct.rs:39:21 + | +39 | #[repr(transparent, align(2))] + | ^^^^^^^^ + +error: cannot derive Unaligned with repr(align(N > 1)) + --> tests/ui-nightly/struct.rs:45:16 + | +45 | #[repr(packed, align(2))] + | ^^^^^^^^ + +error: cannot derive Unaligned with repr(align(N > 1)) + --> tests/ui-nightly/struct.rs:49:18 + | +49 | #[repr(align(1), align(2))] + | ^^^^^^^^ + +error: cannot derive Unaligned with repr(align(N > 1)) + --> tests/ui-nightly/struct.rs:53:8 + | +53 | #[repr(align(2), align(4))] + | ^^^^^^^^ + +error[E0692]: transparent struct cannot have other repr hints + --> tests/ui-nightly/struct.rs:39:8 + | +39 | #[repr(transparent, align(2))] + | ^^^^^^^^^^^ ^^^^^^^^ + +error[E0277]: the trait bound `HasPadding<AsBytes2, true>: ShouldBe<false>` is not satisfied + --> tests/ui-nightly/struct.rs:23:10 + | +23 | #[derive(AsBytes)] + | ^^^^^^^ the trait `ShouldBe<false>` is not implemented for `HasPadding<AsBytes2, true>` + | + = help: the trait `ShouldBe<VALUE>` is implemented for `HasPadding<T, VALUE>` + = help: see issue #48214 + = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/union.rs b/tests/ui-nightly/union.rs index 0252cbe..e7761e0 100644 --- a/tests/ui/union.rs +++ b/tests/ui-nightly/union.rs @@ -5,6 +5,10 @@ #[macro_use] extern crate zerocopy; +#[path = "../util.rs"] +mod util; + +use self::util::AU16; use std::mem::ManuallyDrop; fn main() {} @@ -21,7 +25,7 @@ union AsBytes1<T> { #[derive(AsBytes)] #[repr(C)] -union AsBytes { +union AsBytes2 { foo: u8, bar: [u8; 2], } @@ -34,7 +38,7 @@ union AsBytes { #[repr(C, align(2))] union Unaligned1 { foo: i16, - bar: u16, + bar: AU16, } // Transparent unions are unstable; see issue #60405 diff --git a/tests/ui-nightly/union.stderr b/tests/ui-nightly/union.stderr new file mode 100644 index 0000000..9c1f8dd --- /dev/null +++ b/tests/ui-nightly/union.stderr @@ -0,0 +1,42 @@ +error: unsupported on types with type parameters + --> tests/ui-nightly/union.rs:20:10 + | +20 | #[derive(AsBytes)] + | ^^^^^^^ + | + = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: cannot derive Unaligned with repr(align(N > 1)) + --> tests/ui-nightly/union.rs:38:11 + | +38 | #[repr(C, align(2))] + | ^^^^^^^^ + +error: cannot derive Unaligned with repr(align(N > 1)) + --> tests/ui-nightly/union.rs:54:16 + | +54 | #[repr(packed, align(2))] + | ^^^^^^^^ + +error: cannot derive Unaligned with repr(align(N > 1)) + --> tests/ui-nightly/union.rs:60:18 + | +60 | #[repr(align(1), align(2))] + | ^^^^^^^^ + +error: cannot derive Unaligned with repr(align(N > 1)) + --> tests/ui-nightly/union.rs:66:8 + | +66 | #[repr(align(2), align(4))] + | ^^^^^^^^ + +error[E0277]: the trait bound `HasPadding<AsBytes2, true>: ShouldBe<false>` is not satisfied + --> tests/ui-nightly/union.rs:26:10 + | +26 | #[derive(AsBytes)] + | ^^^^^^^ the trait `ShouldBe<false>` is not implemented for `HasPadding<AsBytes2, true>` + | + = help: the trait `ShouldBe<VALUE>` is implemented for `HasPadding<T, VALUE>` + = help: see issue #48214 + = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-stable/derive_transparent.rs b/tests/ui-stable/derive_transparent.rs new file mode 100644 index 0000000..a99f92c --- /dev/null +++ b/tests/ui-stable/derive_transparent.rs @@ -0,0 +1,36 @@ +// Copyright 2019 The Fuchsia Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +extern crate zerocopy; + +#[path = "../util.rs"] +mod util; + +use core::marker::PhantomData; + +use { + static_assertions::assert_impl_all, + zerocopy::{AsBytes, FromBytes, FromZeroes, Unaligned}, +}; + +use self::util::NotZerocopy; + +fn main() {} + +// Test generic transparent structs + +#[derive(AsBytes, FromZeroes, FromBytes, Unaligned)] +#[repr(transparent)] +struct TransparentStruct<T> { + inner: T, + _phantom: PhantomData<()>, +} + +// It should be legal to derive these traits on a transparent struct, but it +// must also ensure the traits are only implemented when the inner type +// implements them. +assert_impl_all!(TransparentStruct<NotZerocopy>: FromZeroes); +assert_impl_all!(TransparentStruct<NotZerocopy>: FromBytes); +assert_impl_all!(TransparentStruct<NotZerocopy>: AsBytes); +assert_impl_all!(TransparentStruct<NotZerocopy>: Unaligned); diff --git a/tests/ui-stable/derive_transparent.stderr b/tests/ui-stable/derive_transparent.stderr new file mode 100644 index 0000000..3810def --- /dev/null +++ b/tests/ui-stable/derive_transparent.stderr @@ -0,0 +1,111 @@ +error[E0277]: the trait bound `NotZerocopy: FromZeroes` is not satisfied + --> tests/ui-stable/derive_transparent.rs:33:18 + | +33 | assert_impl_all!(TransparentStruct<NotZerocopy>: FromZeroes); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromZeroes` is not implemented for `NotZerocopy` + | + = help: the following other types implement trait `FromZeroes`: + () + AU16 + F32<O> + F64<O> + I128<O> + I16<O> + I32<O> + I64<O> + and $N others +note: required for `TransparentStruct<NotZerocopy>` to implement `FromZeroes` + --> tests/ui-stable/derive_transparent.rs:23:19 + | +23 | #[derive(AsBytes, FromZeroes, FromBytes, Unaligned)] + | ^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +note: required by a bound in `_::{closure#0}::assert_impl_all` + --> tests/ui-stable/derive_transparent.rs:33:1 + | +33 | assert_impl_all!(TransparentStruct<NotZerocopy>: FromZeroes); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `assert_impl_all` + = note: this error originates in the derive macro `FromZeroes` which comes from the expansion of the macro `assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: FromBytes` is not satisfied + --> tests/ui-stable/derive_transparent.rs:34:18 + | +34 | assert_impl_all!(TransparentStruct<NotZerocopy>: FromBytes); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromBytes` is not implemented for `NotZerocopy` + | + = help: the following other types implement trait `FromBytes`: + () + AU16 + F32<O> + F64<O> + I128<O> + I16<O> + I32<O> + I64<O> + and $N others +note: required for `TransparentStruct<NotZerocopy>` to implement `FromBytes` + --> tests/ui-stable/derive_transparent.rs:23:31 + | +23 | #[derive(AsBytes, FromZeroes, FromBytes, Unaligned)] + | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +note: required by a bound in `_::{closure#0}::assert_impl_all` + --> tests/ui-stable/derive_transparent.rs:34:1 + | +34 | assert_impl_all!(TransparentStruct<NotZerocopy>: FromBytes); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `assert_impl_all` + = note: this error originates in the derive macro `FromBytes` which comes from the expansion of the macro `assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: AsBytes` is not satisfied + --> tests/ui-stable/derive_transparent.rs:35:18 + | +35 | assert_impl_all!(TransparentStruct<NotZerocopy>: AsBytes); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsBytes` is not implemented for `NotZerocopy` + | + = help: the following other types implement trait `AsBytes`: + () + AU16 + F32<O> + F64<O> + I128<O> + I16<O> + I32<O> + I64<O> + and $N others +note: required for `TransparentStruct<NotZerocopy>` to implement `AsBytes` + --> tests/ui-stable/derive_transparent.rs:23:10 + | +23 | #[derive(AsBytes, FromZeroes, FromBytes, Unaligned)] + | ^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +note: required by a bound in `_::{closure#0}::assert_impl_all` + --> tests/ui-stable/derive_transparent.rs:35:1 + | +35 | assert_impl_all!(TransparentStruct<NotZerocopy>: AsBytes); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `assert_impl_all` + = note: this error originates in the derive macro `AsBytes` which comes from the expansion of the macro `assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: Unaligned` is not satisfied + --> tests/ui-stable/derive_transparent.rs:36:18 + | +36 | assert_impl_all!(TransparentStruct<NotZerocopy>: Unaligned); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Unaligned` is not implemented for `NotZerocopy` + | + = help: the following other types implement trait `Unaligned`: + () + F32<O> + F64<O> + I128<O> + I16<O> + I32<O> + I64<O> + ManuallyDrop<T> + and $N others +note: required for `TransparentStruct<NotZerocopy>` to implement `Unaligned` + --> tests/ui-stable/derive_transparent.rs:23:42 + | +23 | #[derive(AsBytes, FromZeroes, FromBytes, Unaligned)] + | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +note: required by a bound in `_::{closure#0}::assert_impl_all` + --> tests/ui-stable/derive_transparent.rs:36:1 + | +36 | assert_impl_all!(TransparentStruct<NotZerocopy>: Unaligned); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `assert_impl_all` + = note: this error originates in the derive macro `Unaligned` which comes from the expansion of the macro `assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-stable/enum.rs b/tests/ui-stable/enum.rs index 188b0a6..c3d1e27 100644 --- a/tests/ui-stable/enum.rs +++ b/tests/ui-stable/enum.rs @@ -11,76 +11,97 @@ fn main() {} // Generic errors // -#[derive(FromBytes)] +#[derive(FromZeroes, FromBytes)] #[repr("foo")] enum Generic1 { A, } -#[derive(FromBytes)] +#[derive(FromZeroes, FromBytes)] #[repr(foo)] enum Generic2 { A, } -#[derive(FromBytes)] +#[derive(FromZeroes, FromBytes)] #[repr(transparent)] enum Generic3 { A, } -#[derive(FromBytes)] +#[derive(FromZeroes, FromBytes)] #[repr(u8, u16)] enum Generic4 { A, } -#[derive(FromBytes)] +#[derive(FromZeroes, FromBytes)] enum Generic5 { A, } // +// FromZeroes errors +// + +#[derive(FromZeroes)] +enum FromZeroes1 { + A(u8), +} + +#[derive(FromZeroes)] +enum FromZeroes2 { + A, + B(u8), +} + +#[derive(FromZeroes)] +enum FromZeroes3 { + A = 1, + B, +} + +// // FromBytes errors // -#[derive(FromBytes)] +#[derive(FromZeroes, FromBytes)] #[repr(C)] enum FromBytes1 { A, } -#[derive(FromBytes)] +#[derive(FromZeroes, FromBytes)] #[repr(usize)] enum FromBytes2 { A, } -#[derive(FromBytes)] +#[derive(FromZeroes, FromBytes)] #[repr(isize)] enum FromBytes3 { A, } -#[derive(FromBytes)] +#[derive(FromZeroes, FromBytes)] #[repr(u32)] enum FromBytes4 { A, } -#[derive(FromBytes)] +#[derive(FromZeroes, FromBytes)] #[repr(i32)] enum FromBytes5 { A, } -#[derive(FromBytes)] +#[derive(FromZeroes, FromBytes)] #[repr(u64)] enum FromBytes6 { A, } -#[derive(FromBytes)] +#[derive(FromZeroes, FromBytes)] #[repr(i64)] enum FromBytes7 { A, diff --git a/tests/ui-stable/enum.stderr b/tests/ui-stable/enum.stderr index a72d288..1e35fa6 100644 --- a/tests/ui-stable/enum.stderr +++ b/tests/ui-stable/enum.stderr @@ -23,131 +23,157 @@ error: conflicting representation hints | ^ error: must have a non-align #[repr(...)] attribute in order to guarantee this type's memory layout - --> tests/ui-stable/enum.rs:38:10 + --> tests/ui-stable/enum.rs:38:22 | -38 | #[derive(FromBytes)] - | ^^^^^^^^^ +38 | #[derive(FromZeroes, FromBytes)] + | ^^^^^^^^^ | = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) +error: only C-like enums can implement FromZeroes + --> tests/ui-stable/enum.rs:48:1 + | +48 | / enum FromZeroes1 { +49 | | A(u8), +50 | | } + | |_^ + +error: only C-like enums can implement FromZeroes + --> tests/ui-stable/enum.rs:53:1 + | +53 | / enum FromZeroes2 { +54 | | A, +55 | | B(u8), +56 | | } + | |_^ + +error: FromZeroes only supported on enums with a variant that has a discriminant of `0` + --> tests/ui-stable/enum.rs:59:1 + | +59 | / enum FromZeroes3 { +60 | | A = 1, +61 | | B, +62 | | } + | |_^ + error: FromBytes requires repr of "u8", "u16", "i8", or "i16" - --> tests/ui-stable/enum.rs:48:8 + --> tests/ui-stable/enum.rs:69:8 | -48 | #[repr(C)] +69 | #[repr(C)] | ^ error: FromBytes requires repr of "u8", "u16", "i8", or "i16" - --> tests/ui-stable/enum.rs:54:8 + --> tests/ui-stable/enum.rs:75:8 | -54 | #[repr(usize)] +75 | #[repr(usize)] | ^^^^^ error: FromBytes requires repr of "u8", "u16", "i8", or "i16" - --> tests/ui-stable/enum.rs:60:8 + --> tests/ui-stable/enum.rs:81:8 | -60 | #[repr(isize)] +81 | #[repr(isize)] | ^^^^^ error: FromBytes requires repr of "u8", "u16", "i8", or "i16" - --> tests/ui-stable/enum.rs:66:8 + --> tests/ui-stable/enum.rs:87:8 | -66 | #[repr(u32)] +87 | #[repr(u32)] | ^^^ error: FromBytes requires repr of "u8", "u16", "i8", or "i16" - --> tests/ui-stable/enum.rs:72:8 + --> tests/ui-stable/enum.rs:93:8 | -72 | #[repr(i32)] +93 | #[repr(i32)] | ^^^ error: FromBytes requires repr of "u8", "u16", "i8", or "i16" - --> tests/ui-stable/enum.rs:78:8 + --> tests/ui-stable/enum.rs:99:8 | -78 | #[repr(u64)] +99 | #[repr(u64)] | ^^^ error: FromBytes requires repr of "u8", "u16", "i8", or "i16" - --> tests/ui-stable/enum.rs:84:8 - | -84 | #[repr(i64)] - | ^^^ + --> tests/ui-stable/enum.rs:105:8 + | +105 | #[repr(i64)] + | ^^^ error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1))) - --> tests/ui-stable/enum.rs:94:8 - | -94 | #[repr(C)] - | ^ + --> tests/ui-stable/enum.rs:115:8 + | +115 | #[repr(C)] + | ^ error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1))) - --> tests/ui-stable/enum.rs:100:8 + --> tests/ui-stable/enum.rs:121:8 | -100 | #[repr(u16)] +121 | #[repr(u16)] | ^^^ error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1))) - --> tests/ui-stable/enum.rs:106:8 + --> tests/ui-stable/enum.rs:127:8 | -106 | #[repr(i16)] +127 | #[repr(i16)] | ^^^ error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1))) - --> tests/ui-stable/enum.rs:112:8 + --> tests/ui-stable/enum.rs:133:8 | -112 | #[repr(u32)] +133 | #[repr(u32)] | ^^^ error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1))) - --> tests/ui-stable/enum.rs:118:8 + --> tests/ui-stable/enum.rs:139:8 | -118 | #[repr(i32)] +139 | #[repr(i32)] | ^^^ error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1))) - --> tests/ui-stable/enum.rs:124:8 + --> tests/ui-stable/enum.rs:145:8 | -124 | #[repr(u64)] +145 | #[repr(u64)] | ^^^ error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1))) - --> tests/ui-stable/enum.rs:130:8 + --> tests/ui-stable/enum.rs:151:8 | -130 | #[repr(i64)] +151 | #[repr(i64)] | ^^^ error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1))) - --> tests/ui-stable/enum.rs:136:8 + --> tests/ui-stable/enum.rs:157:8 | -136 | #[repr(usize)] +157 | #[repr(usize)] | ^^^^^ error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1))) - --> tests/ui-stable/enum.rs:142:8 + --> tests/ui-stable/enum.rs:163:8 | -142 | #[repr(isize)] +163 | #[repr(isize)] | ^^^^^ error: cannot derive Unaligned with repr(align(N > 1)) - --> tests/ui-stable/enum.rs:148:12 + --> tests/ui-stable/enum.rs:169:12 | -148 | #[repr(u8, align(2))] +169 | #[repr(u8, align(2))] | ^^^^^^^^ error: cannot derive Unaligned with repr(align(N > 1)) - --> tests/ui-stable/enum.rs:154:12 + --> tests/ui-stable/enum.rs:175:12 | -154 | #[repr(i8, align(2))] +175 | #[repr(i8, align(2))] | ^^^^^^^^ error: cannot derive Unaligned with repr(align(N > 1)) - --> tests/ui-stable/enum.rs:160:18 + --> tests/ui-stable/enum.rs:181:18 | -160 | #[repr(align(1), align(2))] +181 | #[repr(align(1), align(2))] | ^^^^^^^^ error: cannot derive Unaligned with repr(align(N > 1)) - --> tests/ui-stable/enum.rs:166:8 + --> tests/ui-stable/enum.rs:187:8 | -166 | #[repr(align(2), align(4))] +187 | #[repr(align(2), align(4))] | ^^^^^^^^ error[E0565]: meta item in `repr` must be an identifier @@ -161,6 +187,8 @@ error[E0552]: unrecognized representation hint | 21 | #[repr(foo)] | ^^^ + | + = help: valid reprs are `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` error[E0566]: conflicting representation hints --> tests/ui-stable/enum.rs:33:8 @@ -168,6 +196,6 @@ error[E0566]: conflicting representation hints 33 | #[repr(u8, u16)] | ^^ ^^^ | - = note: `#[deny(conflicting_repr_hints)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #68585 <https://github.com/rust-lang/rust/issues/68585> + = note: `#[deny(conflicting_repr_hints)]` on by default diff --git a/tests/ui-stable/late_compile_pass.rs b/tests/ui-stable/late_compile_pass.rs index 3a99c76..1b4c603 100644 --- a/tests/ui-stable/late_compile_pass.rs +++ b/tests/ui-stable/late_compile_pass.rs @@ -5,6 +5,11 @@ #[macro_use] extern crate zerocopy; +#[path = "../util.rs"] +mod util; + +use self::util::{NotZerocopy, AU16}; + fn main() {} // These tests cause errors which are generated by a later compilation pass than @@ -12,12 +17,21 @@ fn main() {} // the compiler will never get to that pass, and so we won't get the errors. // +// FromZeroes errors +// + +#[derive(FromZeroes)] +struct FromZeroes1 { + value: NotZerocopy, +} + +// // FromBytes errors // #[derive(FromBytes)] struct FromBytes1 { - not_from_bytes: &'static str, + value: NotZerocopy, } // @@ -27,8 +41,7 @@ struct FromBytes1 { #[derive(AsBytes)] #[repr(C)] struct AsBytes1 { - a: u8, - b: u16, + value: NotZerocopy, } // @@ -38,7 +51,7 @@ struct AsBytes1 { #[derive(Unaligned)] #[repr(C)] struct Unaligned1 { - aligned: u16, + aligned: AU16, } // This specifically tests a bug we had in an old version of the code in which @@ -47,11 +60,11 @@ struct Unaligned1 { #[repr(C)] struct Unaligned2 { unaligned: u8, - aligned: u16, + aligned: AU16, } #[derive(Unaligned)] #[repr(transparent)] struct Unaligned3 { - aligned: u16, + aligned: AU16, } diff --git a/tests/ui-stable/late_compile_pass.stderr b/tests/ui-stable/late_compile_pass.stderr index 6f3bdbe..eab9b97 100644 --- a/tests/ui-stable/late_compile_pass.stderr +++ b/tests/ui-stable/late_compile_pass.stderr @@ -1,84 +1,136 @@ -error[E0277]: the trait bound `AsBytes1: HasPadding<false>` is not satisfied - --> tests/ui-stable/late_compile_pass.rs:27:10 +error[E0277]: the trait bound `NotZerocopy: FromZeroes` is not satisfied + --> tests/ui-stable/late_compile_pass.rs:23:10 | -27 | #[derive(AsBytes)] - | ^^^^^^^ the trait `HasPadding<false>` is not implemented for `AsBytes1` +23 | #[derive(FromZeroes)] + | ^^^^^^^^^^ the trait `FromZeroes` is not implemented for `NotZerocopy` | - = help: the trait `HasPadding<true>` is implemented for `AsBytes1` -note: required by a bound in `assert_no_padding` - --> tests/ui-stable/late_compile_pass.rs:27:10 - | -27 | #[derive(AsBytes)] - | ^^^^^^^ required by this bound in `assert_no_padding` - = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + = help: the following other types implement trait `FromZeroes`: + () + AU16 + F32<O> + F64<O> + FromZeroes1 + I128<O> + I16<O> + I32<O> + and $N others + = help: see issue #48214 + = note: this error originates in the derive macro `FromZeroes` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0277]: the trait bound `&'static str: FromBytes` is not satisfied - --> tests/ui-stable/late_compile_pass.rs:18:10 +error[E0277]: the trait bound `NotZerocopy: FromBytes` is not satisfied + --> tests/ui-stable/late_compile_pass.rs:32:10 | -18 | #[derive(FromBytes)] - | ^^^^^^^^^ the trait `FromBytes` is not implemented for `&'static str` +32 | #[derive(FromBytes)] + | ^^^^^^^^^ the trait `FromBytes` is not implemented for `NotZerocopy` | = help: the following other types implement trait `FromBytes`: () + AU16 F32<O> F64<O> FromBytes1 I128<O> I16<O> I32<O> - I64<O> - and 36 others -note: required by a bound in `ImplementsFromBytes` - --> tests/ui-stable/late_compile_pass.rs:18:10 + and $N others + = help: see issue #48214 + = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `FromBytes1: FromZeroes` is not satisfied + --> tests/ui-stable/late_compile_pass.rs:32:10 | -18 | #[derive(FromBytes)] - | ^^^^^^^^^ required by this bound in `ImplementsFromBytes` +32 | #[derive(FromBytes)] + | ^^^^^^^^^ the trait `FromZeroes` is not implemented for `FromBytes1` + | + = help: the following other types implement trait `FromZeroes`: + () + AU16 + F32<O> + F64<O> + FromZeroes1 + I128<O> + I16<O> + I32<O> + and $N others +note: required by a bound in `FromBytes` + --> $WORKSPACE/src/lib.rs + | + | pub unsafe trait FromBytes: FromZeroes { + | ^^^^^^^^^^ required by this bound in `FromBytes` = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0277]: the trait bound `u16: Unaligned` is not satisfied - --> tests/ui-stable/late_compile_pass.rs:38:10 +error[E0277]: the trait bound `NotZerocopy: AsBytes` is not satisfied + --> tests/ui-stable/late_compile_pass.rs:41:10 | -38 | #[derive(Unaligned)] - | ^^^^^^^^^ the trait `Unaligned` is not implemented for `u16` +41 | #[derive(AsBytes)] + | ^^^^^^^ the trait `AsBytes` is not implemented for `NotZerocopy` | - = help: the following other types implement trait `Unaligned`: - i8 - u8 -note: required by a bound in `<Unaligned1 as Unaligned>::only_derive_is_allowed_to_implement_this_trait::ImplementsUnaligned` - --> tests/ui-stable/late_compile_pass.rs:38:10 + = help: the following other types implement trait `AsBytes`: + () + AU16 + AsBytes1 + F32<O> + F64<O> + I128<O> + I16<O> + I32<O> + and $N others + = help: see issue #48214 + = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `AU16: Unaligned` is not satisfied + --> tests/ui-stable/late_compile_pass.rs:51:10 + | +51 | #[derive(Unaligned)] + | ^^^^^^^^^ the trait `Unaligned` is not implemented for `AU16` | -38 | #[derive(Unaligned)] - | ^^^^^^^^^ required by this bound in `<Unaligned1 as Unaligned>::only_derive_is_allowed_to_implement_this_trait::ImplementsUnaligned` + = help: the following other types implement trait `Unaligned`: + () + F32<O> + F64<O> + I128<O> + I16<O> + I32<O> + I64<O> + ManuallyDrop<T> + and $N others + = help: see issue #48214 = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0277]: the trait bound `u16: Unaligned` is not satisfied - --> tests/ui-stable/late_compile_pass.rs:46:10 +error[E0277]: the trait bound `AU16: Unaligned` is not satisfied + --> tests/ui-stable/late_compile_pass.rs:59:10 | -46 | #[derive(Unaligned)] - | ^^^^^^^^^ the trait `Unaligned` is not implemented for `u16` +59 | #[derive(Unaligned)] + | ^^^^^^^^^ the trait `Unaligned` is not implemented for `AU16` | = help: the following other types implement trait `Unaligned`: - i8 - u8 -note: required by a bound in `<Unaligned2 as Unaligned>::only_derive_is_allowed_to_implement_this_trait::ImplementsUnaligned` - --> tests/ui-stable/late_compile_pass.rs:46:10 - | -46 | #[derive(Unaligned)] - | ^^^^^^^^^ required by this bound in `<Unaligned2 as Unaligned>::only_derive_is_allowed_to_implement_this_trait::ImplementsUnaligned` + () + F32<O> + F64<O> + I128<O> + I16<O> + I32<O> + I64<O> + ManuallyDrop<T> + and $N others + = help: see issue #48214 = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0277]: the trait bound `u16: Unaligned` is not satisfied - --> tests/ui-stable/late_compile_pass.rs:53:10 +error[E0277]: the trait bound `AU16: Unaligned` is not satisfied + --> tests/ui-stable/late_compile_pass.rs:66:10 | -53 | #[derive(Unaligned)] - | ^^^^^^^^^ the trait `Unaligned` is not implemented for `u16` +66 | #[derive(Unaligned)] + | ^^^^^^^^^ the trait `Unaligned` is not implemented for `AU16` | = help: the following other types implement trait `Unaligned`: - i8 - u8 -note: required by a bound in `<Unaligned3 as Unaligned>::only_derive_is_allowed_to_implement_this_trait::ImplementsUnaligned` - --> tests/ui-stable/late_compile_pass.rs:53:10 - | -53 | #[derive(Unaligned)] - | ^^^^^^^^^ required by this bound in `<Unaligned3 as Unaligned>::only_derive_is_allowed_to_implement_this_trait::ImplementsUnaligned` + () + F32<O> + F64<O> + I128<O> + I16<O> + I32<O> + I64<O> + ManuallyDrop<T> + and $N others + = help: see issue #48214 = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-stable/struct.rs b/tests/ui-stable/struct.rs index ee8fd06..29aa0e8 100644 --- a/tests/ui-stable/struct.rs +++ b/tests/ui-stable/struct.rs @@ -5,6 +5,11 @@ #[macro_use] extern crate zerocopy; +#[path = "../util.rs"] +mod util; + +use self::util::AU16; + fn main() {} // @@ -15,6 +20,13 @@ fn main() {} #[repr(C)] struct AsBytes1<T>(T); +#[derive(AsBytes)] +#[repr(C)] +struct AsBytes2 { + foo: u8, + bar: AU16, +} + // // Unaligned errors // diff --git a/tests/ui-stable/struct.stderr b/tests/ui-stable/struct.stderr index f3a5ccb..a82920e 100644 --- a/tests/ui-stable/struct.stderr +++ b/tests/ui-stable/struct.stderr @@ -1,49 +1,53 @@ -error: unsupported on types with type parameters - --> tests/ui-stable/struct.rs:14:10 +error: unsupported on generic structs that are not repr(transparent) or repr(packed) + --> tests/ui-stable/struct.rs:19:10 | -14 | #[derive(AsBytes)] +19 | #[derive(AsBytes)] | ^^^^^^^ | = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info) error: cannot derive Unaligned with repr(align(N > 1)) - --> tests/ui-stable/struct.rs:23:11 + --> tests/ui-stable/struct.rs:35:11 | -23 | #[repr(C, align(2))] +35 | #[repr(C, align(2))] | ^^^^^^^^ error: cannot derive Unaligned with repr(align(N > 1)) - --> tests/ui-stable/struct.rs:27:21 + --> tests/ui-stable/struct.rs:39:21 | -27 | #[repr(transparent, align(2))] +39 | #[repr(transparent, align(2))] | ^^^^^^^^ error: cannot derive Unaligned with repr(align(N > 1)) - --> tests/ui-stable/struct.rs:33:16 + --> tests/ui-stable/struct.rs:45:16 | -33 | #[repr(packed, align(2))] +45 | #[repr(packed, align(2))] | ^^^^^^^^ error: cannot derive Unaligned with repr(align(N > 1)) - --> tests/ui-stable/struct.rs:37:18 + --> tests/ui-stable/struct.rs:49:18 | -37 | #[repr(align(1), align(2))] +49 | #[repr(align(1), align(2))] | ^^^^^^^^ error: cannot derive Unaligned with repr(align(N > 1)) - --> tests/ui-stable/struct.rs:41:8 + --> tests/ui-stable/struct.rs:53:8 | -41 | #[repr(align(2), align(4))] +53 | #[repr(align(2), align(4))] | ^^^^^^^^ error[E0692]: transparent struct cannot have other repr hints - --> tests/ui-stable/struct.rs:27:8 + --> tests/ui-stable/struct.rs:39:8 | -27 | #[repr(transparent, align(2))] +39 | #[repr(transparent, align(2))] | ^^^^^^^^^^^ ^^^^^^^^ -error[E0587]: type has conflicting packed and align representation hints - --> tests/ui-stable/struct.rs:34:1 +error[E0277]: the trait bound `HasPadding<AsBytes2, true>: ShouldBe<false>` is not satisfied + --> tests/ui-stable/struct.rs:23:10 | -34 | struct Unaligned3; - | ^^^^^^^^^^^^^^^^^ +23 | #[derive(AsBytes)] + | ^^^^^^^ the trait `ShouldBe<false>` is not implemented for `HasPadding<AsBytes2, true>` + | + = help: the trait `ShouldBe<VALUE>` is implemented for `HasPadding<T, VALUE>` + = help: see issue #48214 + = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-stable/union.rs b/tests/ui-stable/union.rs index 0252cbe..e7761e0 100644 --- a/tests/ui-stable/union.rs +++ b/tests/ui-stable/union.rs @@ -5,6 +5,10 @@ #[macro_use] extern crate zerocopy; +#[path = "../util.rs"] +mod util; + +use self::util::AU16; use std::mem::ManuallyDrop; fn main() {} @@ -21,7 +25,7 @@ union AsBytes1<T> { #[derive(AsBytes)] #[repr(C)] -union AsBytes { +union AsBytes2 { foo: u8, bar: [u8; 2], } @@ -34,7 +38,7 @@ union AsBytes { #[repr(C, align(2))] union Unaligned1 { foo: i16, - bar: u16, + bar: AU16, } // Transparent unions are unstable; see issue #60405 diff --git a/tests/ui-stable/union.stderr b/tests/ui-stable/union.stderr index 5726d99..6671271 100644 --- a/tests/ui-stable/union.stderr +++ b/tests/ui-stable/union.stderr @@ -1,51 +1,41 @@ error: unsupported on types with type parameters - --> tests/ui-stable/union.rs:16:10 + --> tests/ui-stable/union.rs:20:10 | -16 | #[derive(AsBytes)] +20 | #[derive(AsBytes)] | ^^^^^^^ | = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info) error: cannot derive Unaligned with repr(align(N > 1)) - --> tests/ui-stable/union.rs:34:11 + --> tests/ui-stable/union.rs:38:11 | -34 | #[repr(C, align(2))] +38 | #[repr(C, align(2))] | ^^^^^^^^ error: cannot derive Unaligned with repr(align(N > 1)) - --> tests/ui-stable/union.rs:50:16 + --> tests/ui-stable/union.rs:54:16 | -50 | #[repr(packed, align(2))] +54 | #[repr(packed, align(2))] | ^^^^^^^^ error: cannot derive Unaligned with repr(align(N > 1)) - --> tests/ui-stable/union.rs:56:18 + --> tests/ui-stable/union.rs:60:18 | -56 | #[repr(align(1), align(2))] +60 | #[repr(align(1), align(2))] | ^^^^^^^^ error: cannot derive Unaligned with repr(align(N > 1)) - --> tests/ui-stable/union.rs:62:8 + --> tests/ui-stable/union.rs:66:8 | -62 | #[repr(align(2), align(4))] +66 | #[repr(align(2), align(4))] | ^^^^^^^^ -error[E0277]: the trait bound `AsBytes: FieldsAreSameSize<true>` is not satisfied - --> tests/ui-stable/union.rs:22:10 +error[E0277]: the trait bound `HasPadding<AsBytes2, true>: ShouldBe<false>` is not satisfied + --> tests/ui-stable/union.rs:26:10 | -22 | #[derive(AsBytes)] - | ^^^^^^^ the trait `FieldsAreSameSize<true>` is not implemented for `AsBytes` +26 | #[derive(AsBytes)] + | ^^^^^^^ the trait `ShouldBe<false>` is not implemented for `HasPadding<AsBytes2, true>` | - = help: the trait `FieldsAreSameSize<false>` is implemented for `AsBytes` -note: required by a bound in `assert_fields_are_same_size` - --> tests/ui-stable/union.rs:22:10 - | -22 | #[derive(AsBytes)] - | ^^^^^^^ required by this bound in `assert_fields_are_same_size` + = help: the trait `ShouldBe<VALUE>` is implemented for `HasPadding<T, VALUE>` + = help: see issue #48214 = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info) - -error[E0587]: type has conflicting packed and align representation hints - --> tests/ui-stable/union.rs:51:1 - | -51 | union Unaligned3 { - | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/late_compile_pass.stderr b/tests/ui/late_compile_pass.stderr deleted file mode 100644 index ce5d9b5..0000000 --- a/tests/ui/late_compile_pass.stderr +++ /dev/null @@ -1,84 +0,0 @@ -error[E0277]: the trait bound `AsBytes1: HasPadding<false>` is not satisfied - --> tests/ui/late_compile_pass.rs:29:8 - | -29 | struct AsBytes1 { - | ^^^^^^^^ the trait `HasPadding<false>` is not implemented for `AsBytes1` - | - = help: the trait `HasPadding<true>` is implemented for `AsBytes1` -note: required by a bound in `assert_no_padding` - --> tests/ui/late_compile_pass.rs:27:10 - | -27 | #[derive(AsBytes)] - | ^^^^^^^ required by this bound in `assert_no_padding` - = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info) - -error[E0277]: the trait bound `&'static str: FromBytes` is not satisfied - --> tests/ui/late_compile_pass.rs:18:10 - | -18 | #[derive(FromBytes)] - | ^^^^^^^^^ the trait `FromBytes` is not implemented for `&'static str` - | - = help: the following other types implement trait `FromBytes`: - () - F32<O> - F64<O> - FromBytes1 - I128<O> - I16<O> - I32<O> - I64<O> - and 36 others -note: required by a bound in `ImplementsFromBytes` - --> tests/ui/late_compile_pass.rs:18:10 - | -18 | #[derive(FromBytes)] - | ^^^^^^^^^ required by this bound in `ImplementsFromBytes` - = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) - -error[E0277]: the trait bound `u16: Unaligned` is not satisfied - --> tests/ui/late_compile_pass.rs:38:10 - | -38 | #[derive(Unaligned)] - | ^^^^^^^^^ the trait `Unaligned` is not implemented for `u16` - | - = help: the following other types implement trait `Unaligned`: - i8 - u8 -note: required by a bound in `<Unaligned1 as Unaligned>::only_derive_is_allowed_to_implement_this_trait::ImplementsUnaligned` - --> tests/ui/late_compile_pass.rs:38:10 - | -38 | #[derive(Unaligned)] - | ^^^^^^^^^ required by this bound in `<Unaligned1 as Unaligned>::only_derive_is_allowed_to_implement_this_trait::ImplementsUnaligned` - = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) - -error[E0277]: the trait bound `u16: Unaligned` is not satisfied - --> tests/ui/late_compile_pass.rs:46:10 - | -46 | #[derive(Unaligned)] - | ^^^^^^^^^ the trait `Unaligned` is not implemented for `u16` - | - = help: the following other types implement trait `Unaligned`: - i8 - u8 -note: required by a bound in `<Unaligned2 as Unaligned>::only_derive_is_allowed_to_implement_this_trait::ImplementsUnaligned` - --> tests/ui/late_compile_pass.rs:46:10 - | -46 | #[derive(Unaligned)] - | ^^^^^^^^^ required by this bound in `<Unaligned2 as Unaligned>::only_derive_is_allowed_to_implement_this_trait::ImplementsUnaligned` - = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) - -error[E0277]: the trait bound `u16: Unaligned` is not satisfied - --> tests/ui/late_compile_pass.rs:53:10 - | -53 | #[derive(Unaligned)] - | ^^^^^^^^^ the trait `Unaligned` is not implemented for `u16` - | - = help: the following other types implement trait `Unaligned`: - i8 - u8 -note: required by a bound in `<Unaligned3 as Unaligned>::only_derive_is_allowed_to_implement_this_trait::ImplementsUnaligned` - --> tests/ui/late_compile_pass.rs:53:10 - | -53 | #[derive(Unaligned)] - | ^^^^^^^^^ required by this bound in `<Unaligned3 as Unaligned>::only_derive_is_allowed_to_implement_this_trait::ImplementsUnaligned` - = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/struct.stderr b/tests/ui/struct.stderr deleted file mode 100644 index b35739e..0000000 --- a/tests/ui/struct.stderr +++ /dev/null @@ -1,49 +0,0 @@ -error: unsupported on types with type parameters - --> tests/ui/struct.rs:14:10 - | -14 | #[derive(AsBytes)] - | ^^^^^^^ - | - = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: cannot derive Unaligned with repr(align(N > 1)) - --> tests/ui/struct.rs:23:11 - | -23 | #[repr(C, align(2))] - | ^^^^^^^^ - -error: cannot derive Unaligned with repr(align(N > 1)) - --> tests/ui/struct.rs:27:21 - | -27 | #[repr(transparent, align(2))] - | ^^^^^^^^ - -error: cannot derive Unaligned with repr(align(N > 1)) - --> tests/ui/struct.rs:33:16 - | -33 | #[repr(packed, align(2))] - | ^^^^^^^^ - -error: cannot derive Unaligned with repr(align(N > 1)) - --> tests/ui/struct.rs:37:18 - | -37 | #[repr(align(1), align(2))] - | ^^^^^^^^ - -error: cannot derive Unaligned with repr(align(N > 1)) - --> tests/ui/struct.rs:41:8 - | -41 | #[repr(align(2), align(4))] - | ^^^^^^^^ - -error[E0692]: transparent struct cannot have other repr hints - --> tests/ui/struct.rs:27:8 - | -27 | #[repr(transparent, align(2))] - | ^^^^^^^^^^^ ^^^^^^^^ - -error[E0587]: type has conflicting packed and align representation hints - --> tests/ui/struct.rs:34:1 - | -34 | struct Unaligned3; - | ^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/union.stderr b/tests/ui/union.stderr deleted file mode 100644 index 4575639..0000000 --- a/tests/ui/union.stderr +++ /dev/null @@ -1,51 +0,0 @@ -error: unsupported on types with type parameters - --> tests/ui/union.rs:16:10 - | -16 | #[derive(AsBytes)] - | ^^^^^^^ - | - = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: cannot derive Unaligned with repr(align(N > 1)) - --> tests/ui/union.rs:34:11 - | -34 | #[repr(C, align(2))] - | ^^^^^^^^ - -error: cannot derive Unaligned with repr(align(N > 1)) - --> tests/ui/union.rs:50:16 - | -50 | #[repr(packed, align(2))] - | ^^^^^^^^ - -error: cannot derive Unaligned with repr(align(N > 1)) - --> tests/ui/union.rs:56:18 - | -56 | #[repr(align(1), align(2))] - | ^^^^^^^^ - -error: cannot derive Unaligned with repr(align(N > 1)) - --> tests/ui/union.rs:62:8 - | -62 | #[repr(align(2), align(4))] - | ^^^^^^^^ - -error[E0277]: the trait bound `AsBytes: FieldsAreSameSize<true>` is not satisfied - --> tests/ui/union.rs:24:7 - | -24 | union AsBytes { - | ^^^^^^^ the trait `FieldsAreSameSize<true>` is not implemented for `AsBytes` - | - = help: the trait `FieldsAreSameSize<false>` is implemented for `AsBytes` -note: required by a bound in `assert_fields_are_same_size` - --> tests/ui/union.rs:22:10 - | -22 | #[derive(AsBytes)] - | ^^^^^^^ required by this bound in `assert_fields_are_same_size` - = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info) - -error[E0587]: type has conflicting packed and align representation hints - --> tests/ui/union.rs:51:1 - | -51 | union Unaligned3 { - | ^^^^^^^^^^^^^^^^ diff --git a/tests/union_as_bytes.rs b/tests/union_as_bytes.rs index fd848cc..62b8827 100644 --- a/tests/union_as_bytes.rs +++ b/tests/union_as_bytes.rs @@ -6,18 +6,7 @@ use std::{marker::PhantomData, option::IntoIter}; -use zerocopy::AsBytes; - -struct IsAsBytes<T: AsBytes>(T); - -// Fail compilation if `$ty: !AsBytes`. -macro_rules! is_as_bytes { - ($ty:ty) => { - const _: () = { - let _: IsAsBytes<$ty>; - }; - }; -} +use {static_assertions::assert_impl_all, zerocopy::AsBytes}; // A union is `AsBytes` if: // - all fields are `AsBytes` @@ -31,7 +20,7 @@ union CZst { a: (), } -is_as_bytes!(CZst); +assert_impl_all!(CZst: AsBytes); #[derive(AsBytes)] #[repr(C)] @@ -40,7 +29,7 @@ union C { b: u8, } -is_as_bytes!(C); +assert_impl_all!(C: AsBytes); // Transparent unions are unstable; see issue #60405 // <https://github.com/rust-lang/rust/issues/60405> for more information. @@ -60,7 +49,7 @@ union CZstPacked { a: (), } -is_as_bytes!(CZstPacked); +assert_impl_all!(CZstPacked: AsBytes); #[derive(AsBytes)] #[repr(C, packed)] @@ -69,7 +58,7 @@ union CPacked { b: i8, } -is_as_bytes!(CPacked); +assert_impl_all!(CPacked: AsBytes); #[derive(AsBytes)] #[repr(C, packed)] @@ -79,4 +68,4 @@ union CMultibytePacked { c: f32, } -is_as_bytes!(CMultibytePacked); +assert_impl_all!(CMultibytePacked: AsBytes); diff --git a/tests/union_from_bytes.rs b/tests/union_from_bytes.rs index ef6d403..dae2491 100644 --- a/tests/union_from_bytes.rs +++ b/tests/union_from_bytes.rs @@ -6,45 +6,37 @@ use std::{marker::PhantomData, option::IntoIter}; -use zerocopy::FromBytes; - -struct IsFromBytes<T: FromBytes>(T); - -// Fail compilation if `$ty: !FromBytes`. -macro_rules! is_from_bytes { - ($ty:ty) => { - const _: () = { - let _: IsFromBytes<$ty>; - }; - }; -} +use { + static_assertions::assert_impl_all, + zerocopy::{FromBytes, FromZeroes}, +}; // A union is `FromBytes` if: // - all fields are `FromBytes` -#[derive(Clone, Copy, FromBytes)] +#[derive(Clone, Copy, FromZeroes, FromBytes)] union Zst { a: (), } -is_from_bytes!(Zst); +assert_impl_all!(Zst: FromBytes); -#[derive(FromBytes)] +#[derive(FromZeroes, FromBytes)] union One { a: u8, } -is_from_bytes!(One); +assert_impl_all!(One: FromBytes); -#[derive(FromBytes)] +#[derive(FromZeroes, FromBytes)] union Two { a: u8, b: Zst, } -is_from_bytes!(Two); +assert_impl_all!(Two: FromBytes); -#[derive(FromBytes)] +#[derive(FromZeroes, FromBytes)] union TypeParams<'a, T: Copy, I: Iterator> where I::Item: Copy, @@ -57,4 +49,4 @@ where g: PhantomData<String>, } -is_from_bytes!(TypeParams<'static, (), IntoIter<()>>); +assert_impl_all!(TypeParams<'static, (), IntoIter<()>>: FromBytes); diff --git a/tests/union_from_zeroes.rs b/tests/union_from_zeroes.rs new file mode 100644 index 0000000..b5822de --- /dev/null +++ b/tests/union_from_zeroes.rs @@ -0,0 +1,52 @@ +// Copyright 2022 The Fuchsia Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#![allow(warnings)] + +#[macro_use] +mod util; + +use std::{marker::PhantomData, option::IntoIter}; + +use {static_assertions::assert_impl_all, zerocopy::FromZeroes}; + +// A union is `FromZeroes` if: +// - all fields are `FromZeroes` + +#[derive(Clone, Copy, FromZeroes)] +union Zst { + a: (), +} + +assert_impl_all!(Zst: FromZeroes); + +#[derive(FromZeroes)] +union One { + a: bool, +} + +assert_impl_all!(One: FromZeroes); + +#[derive(FromZeroes)] +union Two { + a: bool, + b: Zst, +} + +assert_impl_all!(Two: FromZeroes); + +#[derive(FromZeroes)] +union TypeParams<'a, T: Copy, I: Iterator> +where + I::Item: Copy, +{ + a: T, + c: I::Item, + d: u8, + e: PhantomData<&'a [u8]>, + f: PhantomData<&'static str>, + g: PhantomData<String>, +} + +assert_impl_all!(TypeParams<'static, (), IntoIter<()>>: FromZeroes); diff --git a/tests/union_unaligned.rs b/tests/union_unaligned.rs index 076595c..9ccfe93 100644 --- a/tests/union_unaligned.rs +++ b/tests/union_unaligned.rs @@ -6,18 +6,7 @@ use std::{marker::PhantomData, option::IntoIter}; -use zerocopy::Unaligned; - -struct IsUnaligned<T: Unaligned>(T); - -// Fail compilation if `$ty: !Unaligned`. -macro_rules! is_unaligned { - ($ty:ty) => { - const _: () = { - let _: IsUnaligned<$ty>; - }; - }; -} +use {static_assertions::assert_impl_all, zerocopy::Unaligned}; // A union is `Unaligned` if: // - `repr(align)` is no more than 1 and either @@ -31,7 +20,7 @@ union Foo { a: u8, } -is_unaligned!(Foo); +assert_impl_all!(Foo: Unaligned); // Transparent unions are unstable; see issue #60405 // <https://github.com/rust-lang/rust/issues/60405> for more information. @@ -47,10 +36,17 @@ is_unaligned!(Foo); #[derive(Unaligned)] #[repr(packed)] union Baz { + // NOTE: The `u16` type is not guaranteed to have alignment 2, although it + // does on many platforms. However, to fix this would require a custom type + // with a `#[repr(align(2))]` attribute, and `#[repr(packed)]` types are not + // allowed to transitively contain `#[repr(align(...))]` types. Thus, we + // have no choice but to use `u16` here. Luckily, these tests run in CI on + // platforms on which `u16` has alignment 2, so this isn't that big of a + // deal. a: u16, } -is_unaligned!(Baz); +assert_impl_all!(Baz: Unaligned); #[derive(Unaligned)] #[repr(C, align(1))] @@ -58,7 +54,7 @@ union FooAlign { a: u8, } -is_unaligned!(FooAlign); +assert_impl_all!(FooAlign: Unaligned); #[derive(Unaligned)] #[repr(C)] @@ -74,4 +70,4 @@ where g: PhantomData<String>, } -is_unaligned!(TypeParams<'static, (), IntoIter<()>>); +assert_impl_all!(TypeParams<'static, (), IntoIter<()>>: Unaligned); diff --git a/tests/util.rs b/tests/util.rs new file mode 100644 index 0000000..7615d84 --- /dev/null +++ b/tests/util.rs @@ -0,0 +1,16 @@ +// Copyright 2022 The Fuchsia Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +use zerocopy::{AsBytes, FromBytes, FromZeroes}; + +/// A type that doesn't implement any zerocopy traits. +pub struct NotZerocopy(()); + +/// A `u16` with alignment 2. +/// +/// Though `u16` has alignment 2 on some platforms, it's not guaranteed. By +/// contrast, `AU16` is guaranteed to have alignment 2. +#[derive(FromZeroes, FromBytes, AsBytes, Copy, Clone)] +#[repr(C, align(2))] +pub struct AU16(u16); |