Closed
Description
Originally discovered in google/zerocopy#2117
Using zerocopy 0.8.11, the following code succeeds cargo check
on nightly-2024-11-19
but produces a warning on nightly-2024-11-20
:
use zerocopy::KnownLayout;
#[derive(KnownLayout)]
#[repr(C)]
pub struct Test(pub [u8; 32]);
Here's the warning:
$ cargo +nightly-2024-11-20 check
Checking tmp v0.1.0 (.../tmp)
warning: unexpected `cfg` condition name: `coverage_nightly`
--> src/lib.rs:3:10
|
3 | #[derive(KnownLayout)]
| ^^^^^^^^^^^
|
= help: expected names are: `clippy`, `debug_assertions`, `doc`, `docsrs`, `doctest`, `feature`, `fmt_debug`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows`
= help: consider using a Cargo feature instead
= help: or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint:
[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(coverage_nightly)'] }
= help: or consider adding `println!("cargo::rustc-check-cfg=cfg(coverage_nightly)");` to the top of the `build.rs`
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
= note: `#[warn(unexpected_cfgs)]` on by default
= note: this warning originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: `tmp` (lib) generated 1 warning
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.04s
If we remove the #[repr(C)]
attribute, then this succeeds without warning on both toolchains.
Here is the output of cargo expand
both with and without the #[repr(C)]
attribute. You can see that neither include cfg(coverage_nightly)
.
With #[repr(C)]
#![feature(prelude_import)]
#[prelude_import]
use std::prelude::rust_2021::*;
#[macro_use]
extern crate std;
use zerocopy::KnownLayout;
#[repr(C)]
pub struct Test(pub [u8; 32]);
const _: () = {
#[allow(deprecated)]
#[automatically_derived]
unsafe impl ::zerocopy::KnownLayout for Test
where
[u8; 32]: ::zerocopy::KnownLayout,
{
fn only_derive_is_allowed_to_implement_this_trait() {}
type PointerMetadata = <[u8; 32] as ::zerocopy::KnownLayout>::PointerMetadata;
type MaybeUninit = __ZerocopyKnownLayoutMaybeUninit;
const LAYOUT: ::zerocopy::DstLayout = {
use ::zerocopy::util::macro_util::core_reexport::num::NonZeroUsize;
use ::zerocopy::{DstLayout, KnownLayout};
let repr_align = ::zerocopy::util::macro_util::core_reexport::option::Option::None;
let repr_packed = ::zerocopy::util::macro_util::core_reexport::option::Option::None;
DstLayout::new_zst(repr_align)
.extend(<[u8; 32] as KnownLayout>::LAYOUT, repr_packed)
.pad_to_align()
};
#[inline(always)]
fn raw_from_ptr_len(
bytes: ::zerocopy::util::macro_util::core_reexport::ptr::NonNull<u8>,
meta: Self::PointerMetadata,
) -> ::zerocopy::util::macro_util::core_reexport::ptr::NonNull<Self> {
use ::zerocopy::KnownLayout;
let trailing = <[u8; 32] as KnownLayout>::raw_from_ptr_len(bytes, meta);
let slf = trailing.as_ptr() as *mut Self;
unsafe {
::zerocopy::util::macro_util::core_reexport::ptr::NonNull::new_unchecked(
slf,
)
}
}
#[inline(always)]
fn pointer_to_metadata(ptr: *mut Self) -> Self::PointerMetadata {
<[u8; 32]>::pointer_to_metadata(ptr as *mut _)
}
}
#[repr(C)]
#[doc(hidden)]
pub struct __ZerocopyKnownLayoutMaybeUninit(
<[u8; 32] as ::zerocopy::KnownLayout>::MaybeUninit,
)
where
[u8; 32]: ::zerocopy::KnownLayout;
unsafe impl ::zerocopy::KnownLayout for __ZerocopyKnownLayoutMaybeUninit
where
[u8; 32]: ::zerocopy::KnownLayout,
<[u8; 32] as ::zerocopy::KnownLayout>::MaybeUninit: ::zerocopy::KnownLayout,
{
#[allow(clippy::missing_inline_in_public_items)]
fn only_derive_is_allowed_to_implement_this_trait() {}
type PointerMetadata = <Test as ::zerocopy::KnownLayout>::PointerMetadata;
type MaybeUninit = Self;
const LAYOUT: ::zerocopy::DstLayout = <Test as ::zerocopy::KnownLayout>::LAYOUT;
#[inline(always)]
fn raw_from_ptr_len(
bytes: ::zerocopy::util::macro_util::core_reexport::ptr::NonNull<u8>,
meta: Self::PointerMetadata,
) -> ::zerocopy::util::macro_util::core_reexport::ptr::NonNull<Self> {
use ::zerocopy::KnownLayout;
let trailing = <<[u8; 32] as ::zerocopy::KnownLayout>::MaybeUninit as KnownLayout>::raw_from_ptr_len(
bytes,
meta,
);
let slf = trailing.as_ptr() as *mut Self;
unsafe {
::zerocopy::util::macro_util::core_reexport::ptr::NonNull::new_unchecked(
slf,
)
}
}
#[inline(always)]
fn pointer_to_metadata(ptr: *mut Self) -> Self::PointerMetadata {
<<[u8; 32] as ::zerocopy::KnownLayout>::MaybeUninit>::pointer_to_metadata(
ptr as *mut _,
)
}
}
};
Without #[repr(C)]
#![feature(prelude_import)]
#[prelude_import]
use std::prelude::rust_2021::*;
#[macro_use]
extern crate std;
use zerocopy::KnownLayout;
pub struct Test(pub [u8; 32]);
#[allow(deprecated)]
#[automatically_derived]
unsafe impl ::zerocopy::KnownLayout for Test
where
Self: ::zerocopy::util::macro_util::core_reexport::marker::Sized,
{
fn only_derive_is_allowed_to_implement_this_trait() {}
type PointerMetadata = ();
type MaybeUninit = ::zerocopy::util::macro_util::core_reexport::mem::MaybeUninit<
Self,
>;
const LAYOUT: ::zerocopy::DstLayout = ::zerocopy::DstLayout::for_type::<Self>();
#[inline(always)]
fn raw_from_ptr_len(
bytes: ::zerocopy::util::macro_util::core_reexport::ptr::NonNull<u8>,
_meta: (),
) -> ::zerocopy::util::macro_util::core_reexport::ptr::NonNull<Self> {
bytes.cast::<Self>()
}
#[inline(always)]
fn pointer_to_metadata(_ptr: *mut Self) -> () {}
}
Note that, while zerocopy 0.8.11 doesn't emit coverage_nightly
from its custom derives, it does use coverage_nightly
in the library itself. You can see the source code for zerocopy 0.8.11 here.