Upgrade zerocopy-derive to 0.7.29 am: cebe3fc896 am: 9f6a67ebdf

Original change: https://android-review.googlesource.com/c/platform/external/rust/crates/zerocopy-derive/+/2860426

Change-Id: I2fb76b96366c36772669abd8010908c41d3944a8
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 0273786..bdb6bac 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,6 +1,6 @@
 {
   "git": {
-    "sha1": "c150d4f1b75fc21240574b6b7dbbcdc236d388b0"
+    "sha1": "5b76223e0eddea87e0f81429e218d12de94cd954"
   },
   "path_in_vcs": "zerocopy-derive"
 }
\ No newline at end of file
diff --git a/Android.bp b/Android.bp
index 86c3942..4f3f880 100644
--- a/Android.bp
+++ b/Android.bp
@@ -24,9 +24,9 @@
     name: "libzerocopy_derive",
     crate_name: "zerocopy_derive",
     cargo_env_compat: true,
-    cargo_pkg_version: "0.7.5",
+    cargo_pkg_version: "0.7.29",
     srcs: ["src/lib.rs"],
-    edition: "2021",
+    edition: "2018",
     rustlibs: [
         "libproc_macro2",
         "libquote",
diff --git a/Cargo.toml b/Cargo.toml
index 1909eaa..e2be73f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -10,14 +10,14 @@
 # See Cargo.toml.orig for the original contents.
 
 [package]
-edition = "2021"
-rust-version = "1.61.0"
+edition = "2018"
+rust-version = "1.60.0"
 name = "zerocopy-derive"
-version = "0.7.5"
+version = "0.7.29"
 authors = ["Joshua Liebow-Feeser <joshlf@google.com>"]
 exclude = [".*"]
 description = "Custom derive for traits from the zerocopy crate"
-license = "BSD-2-Clause"
+license = "BSD-2-Clause OR Apache-2.0 OR MIT"
 repository = "https://github.com/google/zerocopy"
 
 [lib]
@@ -32,11 +32,9 @@
 [dependencies.syn]
 version = "2.0.31"
 
-[dev-dependencies.rustversion]
-version = "1.0"
-
 [dev-dependencies.static_assertions]
 version = "1.1"
 
 [dev-dependencies.trybuild]
-version = "=1.0.80"
+version = "=1.0.85"
+features = ["diff"]
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index 4cb0f08..96692d8 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,16 +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.
+# Copyright 2019 The Fuchsia Authors
+#
+# Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+# <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+# license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+# This file may not be copied, modified, or distributed except according to
+# those terms.
 
 [package]
-edition = "2021"
+edition = "2018"
 name = "zerocopy-derive"
-version = "0.7.5"
+version = "0.7.29"
 authors = ["Joshua Liebow-Feeser <joshlf@google.com>"]
 description = "Custom derive for traits from the zerocopy crate"
-license = "BSD-2-Clause"
+license = "BSD-2-Clause OR Apache-2.0 OR MIT"
 repository = "https://github.com/google/zerocopy"
-rust-version = "1.61.0"
+rust-version = "1.60.0"
 
 exclude = [".*"]
 
@@ -23,11 +27,11 @@
 syn = "2.0.31"
 
 [dev-dependencies]
-rustversion = "1.0"
 static_assertions = "1.1"
+testutil = { path = "../testutil" }
 # 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"
+trybuild = { version = "=1.0.85", features = ["diff"] }
 zerocopy = { path = "../", features = ["default", "derive"] }
diff --git a/LICENSE-APACHE b/LICENSE-APACHE
new file mode 100644
index 0000000..2dc22c1
--- /dev/null
+++ b/LICENSE-APACHE
@@ -0,0 +1,202 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright 2023 The Fuchsia Authors
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
diff --git a/LICENSE-BSD b/LICENSE-BSD
new file mode 100644
index 0000000..7ed244f
--- /dev/null
+++ b/LICENSE-BSD
@@ -0,0 +1,24 @@
+Copyright 2019 The Fuchsia Authors.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+   * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/LICENSE-MIT b/LICENSE-MIT
new file mode 100644
index 0000000..26e1521
--- /dev/null
+++ b/LICENSE-MIT
@@ -0,0 +1,26 @@
+Copyright 2023 The Fuchsia Authors
+
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
diff --git a/METADATA b/METADATA
index 33d1126..5adef8d 100644
--- a/METADATA
+++ b/METADATA
@@ -5,19 +5,16 @@
 name: "zerocopy-derive"
 description: "Custom derive for traits from the zerocopy crate"
 third_party {
-  url {
-    type: HOMEPAGE
-    value: "https://crates.io/crates/zerocopy-derive"
-  }
-  url {
-    type: ARCHIVE
-    value: "https://static.crates.io/crates/zerocopy-derive/zerocopy-derive-0.7.5.crate"
-  }
-  version: "0.7.5"
   license_type: NOTICE
   last_upgrade_date {
     year: 2023
-    month: 9
-    day: 28
+    month: 12
+    day: 5
+  }
+  homepage: "https://crates.io/crates/zerocopy-derive"
+  identifier {
+    type: "Archive"
+    value: "https://static.crates.io/crates/zerocopy-derive/zerocopy-derive-0.7.29.crate"
+    version: "0.7.29"
   }
 }
diff --git a/src/ext.rs b/src/ext.rs
index ff8a3d6..87cf838 100644
--- a/src/ext.rs
+++ b/src/ext.rs
@@ -1,6 +1,10 @@
-// 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.
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
 
 use syn::{Data, DataEnum, DataStruct, DataUnion, Type};
 
diff --git a/src/lib.rs b/src/lib.rs
index 6b9e3a4..9af8a28 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,6 +1,10 @@
-// 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.
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
 
 //! Derive macros for [zerocopy]'s traits.
 //!
@@ -38,6 +42,17 @@
 
 use {crate::ext::*, crate::repr::*};
 
+// Unwraps a `Result<_, Vec<Error>>`, converting any `Err` value into a
+// `TokenStream` and returning it.
+macro_rules! try_or_print {
+    ($e:expr) => {
+        match $e {
+            Ok(x) => x,
+            Err(errors) => return print_all_errors(errors).into(),
+        }
+    };
+}
+
 // TODO(https://github.com/rust-lang/rust/issues/54140): Some errors could be
 // made better if we could add multiple lines of error output like this:
 //
@@ -55,6 +70,179 @@
 // (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(KnownLayout)]
+pub fn derive_known_layout(ts: proc_macro::TokenStream) -> proc_macro::TokenStream {
+    let ast = syn::parse_macro_input!(ts as DeriveInput);
+
+    let is_repr_c_struct = match &ast.data {
+        Data::Struct(..) => {
+            let reprs = try_or_print!(repr::reprs::<Repr>(&ast.attrs));
+            if reprs.iter().any(|(_meta, repr)| repr == &Repr::C) {
+                Some(reprs)
+            } else {
+                None
+            }
+        }
+        Data::Enum(..) | Data::Union(..) => None,
+    };
+
+    let fields = ast.data.field_types();
+
+    let (require_self_sized, extras) = if let (
+        Some(reprs),
+        Some((trailing_field, leading_fields)),
+    ) = (is_repr_c_struct, fields.split_last())
+    {
+        let repr_align = reprs
+            .iter()
+            .find_map(
+                |(_meta, repr)| {
+                    if let Repr::Align(repr_align) = repr {
+                        Some(repr_align)
+                    } else {
+                        None
+                    }
+                },
+            )
+            .map(|repr_align| quote!(NonZeroUsize::new(#repr_align as usize)))
+            .unwrap_or(quote!(None));
+
+        let repr_packed = reprs
+            .iter()
+            .find_map(|(_meta, repr)| match repr {
+                Repr::Packed => Some(1),
+                Repr::PackedN(repr_packed) => Some(*repr_packed),
+                _ => None,
+            })
+            .map(|repr_packed| quote!(NonZeroUsize::new(#repr_packed as usize)))
+            .unwrap_or(quote!(None));
+
+        (
+            false,
+            quote!(
+                // SAFETY: `LAYOUT` accurately describes the layout of `Self`.
+                // The layout of `Self` is reflected using a sequence of
+                // invocations of `DstLayout::{new_zst,extend,pad_to_align}`.
+                // The documentation of these items vows that invocations in
+                // this manner will acurately describe a type, so long as:
+                //
+                //  - that type is `repr(C)`,
+                //  - its fields are enumerated in the order they appear,
+                //  - the presence of `repr_align` and `repr_packed` are correctly accounted for.
+                //
+                // We respect all three of these preconditions here. This
+                // expansion is only used if `is_repr_c_struct`, we enumerate
+                // the fields in order, and we extract the values of `align(N)`
+                // and `packed(N)`.
+                const LAYOUT: ::zerocopy::DstLayout = {
+                    use ::zerocopy::macro_util::core_reexport::num::NonZeroUsize;
+                    use ::zerocopy::{DstLayout, KnownLayout};
+
+                    let repr_align = #repr_align;
+                    let repr_packed = #repr_packed;
+
+                    DstLayout::new_zst(repr_align)
+                        #(.extend(DstLayout::for_type::<#leading_fields>(), repr_packed))*
+                        .extend(<#trailing_field as KnownLayout>::LAYOUT, repr_packed)
+                        .pad_to_align()
+                };
+
+                // SAFETY:
+                // - The recursive call to `raw_from_ptr_len` preserves both address and provenance.
+                // - The `as` cast preserves both address and provenance.
+                // - `NonNull::new_unchecked` preserves both address and provenance.
+                #[inline(always)]
+                fn raw_from_ptr_len(
+                    bytes: ::zerocopy::macro_util::core_reexport::ptr::NonNull<u8>,
+                    elems: usize,
+                ) -> ::zerocopy::macro_util::core_reexport::ptr::NonNull<Self> {
+                    use ::zerocopy::{KnownLayout};
+                    let trailing = <#trailing_field as KnownLayout>::raw_from_ptr_len(bytes, elems);
+                    let slf = trailing.as_ptr() as *mut Self;
+                    // SAFETY: Constructed from `trailing`, which is non-null.
+                    unsafe { ::zerocopy::macro_util::core_reexport::ptr::NonNull::new_unchecked(slf) }
+                }
+            ),
+        )
+    } else {
+        // For enums, unions, and non-`repr(C)` structs, we require that
+        // `Self` is sized, and as a result don't need to reason about the
+        // internals of the type.
+        (
+            true,
+            quote!(
+                // SAFETY: `LAYOUT` is guaranteed to accurately describe the
+                // layout of `Self`, because that is the documented safety
+                // contract of `DstLayout::for_type`.
+                const LAYOUT: ::zerocopy::DstLayout = ::zerocopy::DstLayout::for_type::<Self>();
+
+                // SAFETY: `.cast` preserves address and provenance.
+                //
+                // TODO(#429): Add documentation to `.cast` that promises that
+                // it preserves provenance.
+                #[inline(always)]
+                fn raw_from_ptr_len(
+                    bytes: ::zerocopy::macro_util::core_reexport::ptr::NonNull<u8>,
+                    _elems: usize,
+                ) -> ::zerocopy::macro_util::core_reexport::ptr::NonNull<Self> {
+                    bytes.cast::<Self>()
+                }
+            ),
+        )
+    };
+
+    match &ast.data {
+        Data::Struct(strct) => {
+            let require_trait_bound_on_field_types = if require_self_sized {
+                RequireBoundedFields::No
+            } else {
+                RequireBoundedFields::Trailing
+            };
+
+            // A bound on the trailing field is required, since structs are
+            // unsized if their trailing field is unsized. Reflecting the layout
+            // of an usized trailing field requires that the field is
+            // `KnownLayout`.
+            impl_block(
+                &ast,
+                strct,
+                Trait::KnownLayout,
+                require_trait_bound_on_field_types,
+                require_self_sized,
+                None,
+                Some(extras),
+            )
+        }
+        Data::Enum(enm) => {
+            // A bound on the trailing field is not required, since enums cannot
+            // currently be unsized.
+            impl_block(
+                &ast,
+                enm,
+                Trait::KnownLayout,
+                RequireBoundedFields::No,
+                true,
+                None,
+                Some(extras),
+            )
+        }
+        Data::Union(unn) => {
+            // A bound on the trailing field is not required, since unions
+            // cannot currently be unsized.
+            impl_block(
+                &ast,
+                unn,
+                Trait::KnownLayout,
+                RequireBoundedFields::No,
+                true,
+                None,
+                Some(extras),
+            )
+        }
+    }
+    .into()
+}
+
 #[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);
@@ -99,17 +287,6 @@
     .into()
 }
 
-// Unwraps a `Result<_, Vec<Error>>`, converting any `Err` value into a
-// `TokenStream` and returning it.
-macro_rules! try_or_print {
-    ($e:expr) => {
-        match $e {
-            Ok(x) => x,
-            Err(errors) => return print_all_errors(errors),
-        }
-    };
-}
-
 const STRUCT_UNION_ALLOWED_REPR_COMBINATIONS: &[&[StructRepr]] = &[
     &[StructRepr::C],
     &[StructRepr::Transparent],
@@ -121,7 +298,7 @@
 // - all fields are `FromZeroes`
 
 fn derive_from_zeroes_struct(ast: &DeriveInput, strct: &DataStruct) -> proc_macro2::TokenStream {
-    impl_block(ast, strct, "FromZeroes", true, None)
+    impl_block(ast, strct, Trait::FromZeroes, RequireBoundedFields::Yes, false, None, None)
 }
 
 // An enum is `FromZeroes` if:
@@ -155,21 +332,21 @@
         .to_compile_error();
     }
 
-    impl_block(ast, enm, "FromZeroes", true, None)
+    impl_block(ast, enm, Trait::FromZeroes, RequireBoundedFields::Yes, false, None, 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)
+    impl_block(ast, unn, Trait::FromZeroes, RequireBoundedFields::Yes, false, None, 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, None)
+    impl_block(ast, strct, Trait::FromBytes, RequireBoundedFields::Yes, false, None, None)
 }
 
 // An enum is `FromBytes` if:
@@ -212,7 +389,7 @@
         .to_compile_error();
     }
 
-    impl_block(ast, enm, "FromBytes", true, None)
+    impl_block(ast, enm, Trait::FromBytes, RequireBoundedFields::Yes, false, None, None)
 }
 
 #[rustfmt::skip]
@@ -243,7 +420,7 @@
 // - all fields are `FromBytes`
 
 fn derive_from_bytes_union(ast: &DeriveInput, unn: &DataUnion) -> proc_macro2::TokenStream {
-    impl_block(ast, unn, "FromBytes", true, None)
+    impl_block(ast, unn, Trait::FromBytes, RequireBoundedFields::Yes, false, None, None)
 }
 
 // A struct is `AsBytes` if:
@@ -277,7 +454,7 @@
     //   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)
+    impl_block(ast, strct, Trait::AsBytes, RequireBoundedFields::Yes, false, padding_check, None)
 }
 
 const STRUCT_UNION_AS_BYTES_CFG: Config<StructRepr> = Config {
@@ -300,7 +477,7 @@
     // 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, None)
+    impl_block(ast, enm, Trait::AsBytes, RequireBoundedFields::No, false, None, None)
 }
 
 #[rustfmt::skip]
@@ -342,7 +519,15 @@
 
     try_or_print!(STRUCT_UNION_AS_BYTES_CFG.validate_reprs(ast));
 
-    impl_block(ast, unn, "AsBytes", true, Some(PaddingCheck::Union))
+    impl_block(
+        ast,
+        unn,
+        Trait::AsBytes,
+        RequireBoundedFields::Yes,
+        false,
+        Some(PaddingCheck::Union),
+        None,
+    )
 }
 
 // A struct is `Unaligned` if:
@@ -353,9 +538,9 @@
 
 fn derive_unaligned_struct(ast: &DeriveInput, strct: &DataStruct) -> proc_macro2::TokenStream {
     let reprs = try_or_print!(STRUCT_UNION_UNALIGNED_CFG.validate_reprs(ast));
-    let require_trait_bound = !reprs.contains(&StructRepr::Packed);
+    let require_trait_bounds_on_field_types = (!reprs.contains(&StructRepr::Packed)).into();
 
-    impl_block(ast, strct, "Unaligned", require_trait_bound, None)
+    impl_block(ast, strct, Trait::Unaligned, require_trait_bounds_on_field_types, false, None, None)
 }
 
 const STRUCT_UNION_UNALIGNED_CFG: Config<StructRepr> = Config {
@@ -383,10 +568,10 @@
     let _: Vec<repr::EnumRepr> = try_or_print!(ENUM_UNALIGNED_CFG.validate_reprs(ast));
 
     // C-like enums cannot currently have type parameters, so this value of true
-    // 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, None)
+    // for `require_trait_bound_on_field_types` 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, Trait::Unaligned, RequireBoundedFields::Yes, false, None, None)
 }
 
 #[rustfmt::skip]
@@ -422,9 +607,9 @@
 
 fn derive_unaligned_union(ast: &DeriveInput, unn: &DataUnion) -> proc_macro2::TokenStream {
     let reprs = try_or_print!(STRUCT_UNION_UNALIGNED_CFG.validate_reprs(ast));
-    let require_trait_bound = !reprs.contains(&StructRepr::Packed);
+    let require_trait_bound_on_field_types = (!reprs.contains(&StructRepr::Packed)).into();
 
-    impl_block(ast, unn, "Unaligned", require_trait_bound, None)
+    impl_block(ast, unn, Trait::Unaligned, require_trait_bound_on_field_types, false, None, None)
 }
 
 // This enum describes what kind of padding check needs to be generated for the
@@ -449,12 +634,45 @@
     }
 }
 
+#[derive(Debug, Eq, PartialEq)]
+enum Trait {
+    KnownLayout,
+    FromZeroes,
+    FromBytes,
+    AsBytes,
+    Unaligned,
+}
+
+impl Trait {
+    fn ident(&self) -> Ident {
+        Ident::new(format!("{:?}", self).as_str(), Span::call_site())
+    }
+}
+
+#[derive(Debug, Eq, PartialEq)]
+enum RequireBoundedFields {
+    No,
+    Yes,
+    Trailing,
+}
+
+impl From<bool> for RequireBoundedFields {
+    fn from(do_require: bool) -> Self {
+        match do_require {
+            true => Self::Yes,
+            false => Self::No,
+        }
+    }
+}
+
 fn impl_block<D: DataExt>(
     input: &DeriveInput,
     data: &D,
-    trait_name: &str,
-    require_trait_bound: bool,
+    trt: Trait,
+    require_trait_bound_on_field_types: RequireBoundedFields,
+    require_self_sized: bool,
     padding_check: Option<PaddingCheck>,
+    extras: Option<proc_macro2::TokenStream>,
 ) -> proc_macro2::TokenStream {
     // In this documentation, we will refer to this hypothetical struct:
     //
@@ -515,14 +733,15 @@
     //       = note: required by `zerocopy::Unaligned`
 
     let type_ident = &input.ident;
-    let trait_ident = Ident::new(trait_name, Span::call_site());
+    let trait_ident = trt.ident();
     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<_>>();
+    let bound_tt = |ty| parse_quote!(#ty: ::zerocopy::#trait_ident);
+    let field_type_bounds: Vec<_> = match (require_trait_bound_on_field_types, &field_types[..]) {
+        (RequireBoundedFields::Yes, _) => field_types.iter().map(bound_tt).collect(),
+        (RequireBoundedFields::No, _) | (RequireBoundedFields::Trailing, []) => vec![],
+        (RequireBoundedFields::Trailing, [.., last]) => vec![bound_tt(last)],
+    };
 
     // Don't bother emitting a padding check if there are no fields.
     #[allow(unstable_name_collisions)] // See `BoolExt` below
@@ -530,11 +749,13 @@
         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>
+            ::zerocopy::macro_util::HasPadding<#type_ident, {::zerocopy::#validator_macro!(#type_ident, #(#fields),*)}>:
+                ::zerocopy::macro_util::ShouldBe<false>
         )
     });
 
+    let self_sized_bound = if require_self_sized { Some(parse_quote!(Self: Sized)) } else { None };
+
     let bounds = input
         .generics
         .where_clause
@@ -543,7 +764,8 @@
         .into_iter()
         .flatten()
         .chain(field_type_bounds.iter())
-        .chain(padding_check_bound.iter());
+        .chain(padding_check_bound.iter())
+        .chain(self_sized_bound.iter());
 
     // The parameters with trait bounds, but without type defaults.
     let params = input.generics.params.clone().into_iter().map(|mut param| {
@@ -554,22 +776,34 @@
         }
         quote!(#param)
     });
+
     // The identifiers of the parameters without trait bounds or type defaults.
     let param_idents = input.generics.params.iter().map(|param| match param {
         GenericParam::Type(ty) => {
             let ident = &ty.ident;
             quote!(#ident)
         }
-        GenericParam::Lifetime(l) => quote!(#l),
-        GenericParam::Const(cnst) => quote!(#cnst),
+        GenericParam::Lifetime(l) => {
+            let ident = &l.lifetime;
+            quote!(#ident)
+        }
+        GenericParam::Const(cnst) => {
+            let ident = &cnst.ident;
+            quote!({#ident})
+        }
     });
 
     quote! {
-        unsafe impl < #(#params),* > zerocopy::#trait_ident for #type_ident < #(#param_idents),* >
+        // TODO(#553): Add a test that generates a warning when
+        // `#[allow(deprecated)]` isn't present.
+        #[allow(deprecated)]
+        unsafe impl < #(#params),* > ::zerocopy::#trait_ident for #type_ident < #(#param_idents),* >
         where
             #(#bounds,)*
         {
             fn only_derive_is_allowed_to_implement_this_trait() {}
+
+            #extras
         }
     }
 }
diff --git a/src/repr.rs b/src/repr.rs
index 5997ad2..f4f2788 100644
--- a/src/repr.rs
+++ b/src/repr.rs
@@ -1,6 +1,10 @@
-// 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.
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
 
 use core::fmt::{self, Display, Formatter};
 
@@ -102,23 +106,24 @@
 // etc), and provide implementations of `KindRepr`, `Ord`, and `Display`, and
 // those traits' super-traits.
 macro_rules! define_kind_specific_repr {
-    ($type_name:expr, $repr_name:ident, $($repr_variant:ident),*) => {
+    ($type_name:expr, $repr_name:ident, [ $($repr_variant:ident),* ] , [ $($repr_variant_aligned:ident),* ]) => {
         #[derive(Copy, Clone, Debug, Eq, PartialEq)]
         pub enum $repr_name {
             $($repr_variant,)*
-            Align(u64),
+            $($repr_variant_aligned(u64),)*
         }
 
         impl KindRepr for $repr_name {
             fn is_align(&self) -> bool {
                 match self {
-                    $repr_name::Align(_) => true,
+                    $($repr_name::$repr_variant_aligned(_) => true,)*
                     _ => false,
                 }
             }
 
             fn is_align_gt_one(&self) -> bool {
                 match self {
+                    // `packed(n)` only lowers alignment
                     $repr_name::Align(n) => n > &1,
                     _ => false,
                 }
@@ -127,7 +132,7 @@
             fn parse(meta: &Meta) -> syn::Result<$repr_name> {
                 match Repr::from_meta(meta)? {
                     $(Repr::$repr_variant => Ok($repr_name::$repr_variant),)*
-                    Repr::Align(u) => Ok($repr_name::Align(u)),
+                    $(Repr::$repr_variant_aligned(u) => Ok($repr_name::$repr_variant_aligned(u)),)*
                     _ => Err(Error::new_spanned(meta, concat!("unsupported representation for deriving FromBytes, AsBytes, or Unaligned on ", $type_name)))
                 }
             }
@@ -151,20 +156,23 @@
             fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
                 match self {
                     $($repr_name::$repr_variant => Repr::$repr_variant,)*
-                    $repr_name::Align(u) => Repr::Align(*u),
+                    $($repr_name::$repr_variant_aligned(u) => Repr::$repr_variant_aligned(*u),)*
                 }.fmt(f)
             }
         }
     }
 }
 
-define_kind_specific_repr!("a struct", StructRepr, C, Transparent, Packed);
+define_kind_specific_repr!("a struct", StructRepr, [C, Transparent, Packed], [Align, PackedN]);
 define_kind_specific_repr!(
-    "an enum", EnumRepr, C, U8, U16, U32, U64, Usize, I8, I16, I32, I64, Isize
+    "an enum",
+    EnumRepr,
+    [C, U8, U16, U32, U64, Usize, I8, I16, I32, I64, Isize],
+    [Align]
 );
 
 // All representations known to Rust.
-#[derive(Copy, Clone, Eq, PartialEq)]
+#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
 pub enum Repr {
     U8,
     U16,
@@ -179,40 +187,58 @@
     C,
     Transparent,
     Packed,
+    PackedN(u64),
     Align(u64),
 }
 
 impl Repr {
     fn from_meta(meta: &Meta) -> Result<Repr, Error> {
-        match meta {
-            Meta::Path(path) => {
-                let ident = path
-                    .get_ident()
-                    .ok_or_else(|| Error::new_spanned(meta, "unrecognized representation hint"))?;
-                match format!("{}", ident).as_str() {
-                    "u8" => return Ok(Repr::U8),
-                    "u16" => return Ok(Repr::U16),
-                    "u32" => return Ok(Repr::U32),
-                    "u64" => return Ok(Repr::U64),
-                    "usize" => return Ok(Repr::Usize),
-                    "i8" => return Ok(Repr::I8),
-                    "i16" => return Ok(Repr::I16),
-                    "i32" => return Ok(Repr::I32),
-                    "i64" => return Ok(Repr::I64),
-                    "isize" => return Ok(Repr::Isize),
-                    "C" => return Ok(Repr::C),
-                    "transparent" => return Ok(Repr::Transparent),
-                    "packed" => return Ok(Repr::Packed),
-                    _ => {}
-                }
-            }
-            Meta::List(list) => {
-                return Ok(Repr::Align(list.parse_args::<LitInt>()?.base10_parse::<u64>()?))
-            }
-            _ => {}
-        }
+        let (path, list) = match meta {
+            Meta::Path(path) => (path, None),
+            Meta::List(list) => (&list.path, Some(list)),
+            _ => return Err(Error::new_spanned(meta, "unrecognized representation hint")),
+        };
 
-        Err(Error::new_spanned(meta, "unrecognized representation hint"))
+        let ident = path
+            .get_ident()
+            .ok_or_else(|| Error::new_spanned(meta, "unrecognized representation hint"))?;
+
+        Ok(match (ident.to_string().as_str(), list) {
+            ("u8", None) => Repr::U8,
+            ("u16", None) => Repr::U16,
+            ("u32", None) => Repr::U32,
+            ("u64", None) => Repr::U64,
+            ("usize", None) => Repr::Usize,
+            ("i8", None) => Repr::I8,
+            ("i16", None) => Repr::I16,
+            ("i32", None) => Repr::I32,
+            ("i64", None) => Repr::I64,
+            ("isize", None) => Repr::Isize,
+            ("C", None) => Repr::C,
+            ("transparent", None) => Repr::Transparent,
+            ("packed", None) => Repr::Packed,
+            ("packed", Some(list)) => {
+                Repr::PackedN(list.parse_args::<LitInt>()?.base10_parse::<u64>()?)
+            }
+            ("align", Some(list)) => {
+                Repr::Align(list.parse_args::<LitInt>()?.base10_parse::<u64>()?)
+            }
+            _ => return Err(Error::new_spanned(meta, "unrecognized representation hint")),
+        })
+    }
+}
+
+impl KindRepr for Repr {
+    fn is_align(&self) -> bool {
+        false
+    }
+
+    fn is_align_gt_one(&self) -> bool {
+        false
+    }
+
+    fn parse(meta: &Meta) -> syn::Result<Self> {
+        Self::from_meta(meta)
     }
 }
 
@@ -221,6 +247,9 @@
         if let Repr::Align(n) = self {
             return write!(f, "repr(align({}))", n);
         }
+        if let Repr::PackedN(n) = self {
+            return write!(f, "repr(packed({}))", n);
+        }
         write!(
             f,
             "repr({})",
@@ -244,7 +273,7 @@
     }
 }
 
-fn reprs<R: KindRepr>(attrs: &[Attribute]) -> Result<Vec<(Meta, R)>, Vec<Error>> {
+pub(crate) fn reprs<R: KindRepr>(attrs: &[Attribute]) -> Result<Vec<(Meta, R)>, Vec<Error>> {
     let mut reprs = Vec::new();
     let mut errors = Vec::new();
     for attr in attrs {
diff --git a/tests/enum_as_bytes.rs b/tests/enum_as_bytes.rs
index e1b8efd..e305bc4 100644
--- a/tests/enum_as_bytes.rs
+++ b/tests/enum_as_bytes.rs
@@ -1,6 +1,10 @@
-// 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.
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
 
 #![allow(warnings)]
 
diff --git a/tests/enum_from_bytes.rs b/tests/enum_from_bytes.rs
index 09fe847..4717a8d 100644
--- a/tests/enum_from_bytes.rs
+++ b/tests/enum_from_bytes.rs
@@ -1,6 +1,10 @@
-// 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.
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
 
 #![allow(warnings)]
 
diff --git a/tests/enum_from_zeroes.rs b/tests/enum_from_zeroes.rs
index 3fedcb1..c6bb675 100644
--- a/tests/enum_from_zeroes.rs
+++ b/tests/enum_from_zeroes.rs
@@ -1,6 +1,10 @@
-// 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.
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
 
 #![allow(warnings)]
 
diff --git a/tests/enum_known_layout.rs b/tests/enum_known_layout.rs
new file mode 100644
index 0000000..49a6765
--- /dev/null
+++ b/tests/enum_known_layout.rs
@@ -0,0 +1,46 @@
+// 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 {core::marker::PhantomData, static_assertions::assert_impl_all, zerocopy::KnownLayout};
+
+#[derive(KnownLayout)]
+enum Foo {
+    A,
+}
+
+assert_impl_all!(Foo: KnownLayout);
+
+#[derive(KnownLayout)]
+enum Bar {
+    A = 0,
+}
+
+assert_impl_all!(Bar: KnownLayout);
+
+#[derive(KnownLayout)]
+enum Baz {
+    A = 1,
+    B = 0,
+}
+
+assert_impl_all!(Baz: KnownLayout);
+
+// Deriving `KnownLayout` should work if the enum has bounded parameters.
+
+#[derive(KnownLayout)]
+#[repr(C)]
+enum WithParams<'a: 'b, 'b: 'a, const N: usize, T: 'a + 'b + KnownLayout>
+where
+    'a: 'b,
+    'b: 'a,
+    T: 'a + 'b + KnownLayout,
+{
+    Variant([T; N], PhantomData<&'a &'b ()>),
+}
+
+assert_impl_all!(WithParams<'static, 'static, 42, u8>: KnownLayout);
diff --git a/tests/enum_unaligned.rs b/tests/enum_unaligned.rs
index 1c7cb77..152ce27 100644
--- a/tests/enum_unaligned.rs
+++ b/tests/enum_unaligned.rs
@@ -1,6 +1,10 @@
-// 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.
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
 
 #![allow(warnings)]
 
diff --git a/tests/hygiene.rs b/tests/hygiene.rs
index 9209bcd..b7b838d 100644
--- a/tests/hygiene.rs
+++ b/tests/hygiene.rs
@@ -1,9 +1,14 @@
-// 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.
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
 
 // Make sure that macro hygiene will ensure that when we reference "zerocopy",
-// that will work properly even if they've renamed the crate.
+// that will work properly even if they've renamed the crate and have not
+// imported its traits.
 
 #![allow(warnings)]
 
@@ -14,12 +19,11 @@
 
 use std::{marker::PhantomData, option::IntoIter};
 
-use {
-    _zerocopy::{FromBytes, FromZeroes, Unaligned},
-    static_assertions::assert_impl_all,
-};
+use static_assertions::assert_impl_all;
 
-#[derive(FromZeroes, FromBytes, Unaligned)]
+#[derive(
+    _zerocopy::KnownLayout, _zerocopy::FromZeroes, _zerocopy::FromBytes, _zerocopy::Unaligned,
+)]
 #[repr(C)]
 struct TypeParams<'a, T, I: Iterator> {
     a: T,
@@ -30,4 +34,10 @@
     g: PhantomData<String>,
 }
 
-assert_impl_all!(TypeParams<'static, (), IntoIter<()>>: FromZeroes, FromBytes, Unaligned);
+assert_impl_all!(
+    TypeParams<'static, (), IntoIter<()>>:
+        _zerocopy::KnownLayout,
+        _zerocopy::FromZeroes,
+        _zerocopy::FromBytes,
+        _zerocopy::Unaligned
+);
diff --git a/tests/paths_and_modules.rs b/tests/paths_and_modules.rs
index 8ca3aa2..a01983b 100644
--- a/tests/paths_and_modules.rs
+++ b/tests/paths_and_modules.rs
@@ -1,6 +1,10 @@
-// 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.
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
 
 #![allow(warnings)]
 
diff --git a/tests/priv_in_pub.rs b/tests/priv_in_pub.rs
index f61568a..5f7d874 100644
--- a/tests/priv_in_pub.rs
+++ b/tests/priv_in_pub.rs
@@ -1,8 +1,12 @@
-// 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.
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
 
-use zerocopy::{AsBytes, FromBytes, FromZeroes, Unaligned};
+use zerocopy::{AsBytes, FromBytes, FromZeroes, KnownLayout, Unaligned};
 
 // These derives do not result in E0446 as of Rust 1.59.0, because of
 // https://github.com/rust-lang/rust/pull/90586.
@@ -11,10 +15,10 @@
 // bounds for field types (i.e., the emission of E0446 for private field
 // types).
 
-#[derive(AsBytes, FromZeroes, FromBytes, Unaligned)]
+#[derive(KnownLayout, AsBytes, FromZeroes, FromBytes, Unaligned)]
 #[repr(C)]
 pub struct Public(Private);
 
-#[derive(AsBytes, FromZeroes, FromBytes, Unaligned)]
+#[derive(KnownLayout, AsBytes, FromZeroes, FromBytes, Unaligned)]
 #[repr(C)]
 struct Private(());
diff --git a/tests/struct_as_bytes.rs b/tests/struct_as_bytes.rs
index e1507aa..3c71bf0 100644
--- a/tests/struct_as_bytes.rs
+++ b/tests/struct_as_bytes.rs
@@ -1,6 +1,10 @@
-// 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.
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
 
 #![allow(warnings)]
 
@@ -76,6 +80,18 @@
 assert_impl_all!(CPacked: AsBytes);
 
 #[derive(AsBytes)]
+#[repr(C, packed(2))]
+// The same caveats as for CPacked apply - we're assuming u64 is at least
+// 4-byte aligned by default. Without packed(2), this should fail, as there
+// would be padding between a/b assuming u64 is 4+ byte aligned.
+struct CPacked2 {
+    a: u16,
+    b: u64,
+}
+
+assert_impl_all!(CPacked2: AsBytes);
+
+#[derive(AsBytes)]
 #[repr(C, packed)]
 struct CPackedGeneric<T, U: ?Sized> {
     t: T,
@@ -128,3 +144,18 @@
 }
 
 assert_impl_all!(Unsized: AsBytes);
+
+// Deriving `AsBytes` should work if the struct has bounded parameters.
+
+#[derive(AsBytes)]
+#[repr(transparent)]
+struct WithParams<'a: 'b, 'b: 'a, const N: usize, T: 'a + 'b + AsBytes>(
+    [T; N],
+    PhantomData<&'a &'b ()>,
+)
+where
+    'a: 'b,
+    'b: 'a,
+    T: 'a + 'b + AsBytes;
+
+assert_impl_all!(WithParams<'static, 'static, 42, u8>: AsBytes);
diff --git a/tests/struct_from_bytes.rs b/tests/struct_from_bytes.rs
index 5dc68d2..98f03d1 100644
--- a/tests/struct_from_bytes.rs
+++ b/tests/struct_from_bytes.rs
@@ -1,6 +1,10 @@
-// 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.
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
 
 #![allow(warnings)]
 
@@ -58,3 +62,18 @@
 assert_impl_all!(TypeParams<'static, (), IntoIter<()>>: FromBytes);
 assert_impl_all!(TypeParams<'static, AU16, IntoIter<()>>: FromBytes);
 assert_impl_all!(TypeParams<'static, [AU16], IntoIter<()>>: FromBytes);
+
+// Deriving `FromBytes` should work if the struct has bounded parameters.
+
+#[derive(FromZeroes, FromBytes)]
+#[repr(transparent)]
+struct WithParams<'a: 'b, 'b: 'a, const N: usize, T: 'a + 'b + FromBytes>(
+    [T; N],
+    PhantomData<&'a &'b ()>,
+)
+where
+    'a: 'b,
+    'b: 'a,
+    T: 'a + 'b + FromBytes;
+
+assert_impl_all!(WithParams<'static, 'static, 42, u8>: FromBytes);
diff --git a/tests/struct_from_zeroes.rs b/tests/struct_from_zeroes.rs
index e9609d1..75d8245 100644
--- a/tests/struct_from_zeroes.rs
+++ b/tests/struct_from_zeroes.rs
@@ -1,6 +1,10 @@
-// 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.
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
 
 #![allow(warnings)]
 
@@ -56,3 +60,18 @@
 assert_impl_all!(TypeParams<'static, (), IntoIter<()>>: FromZeroes);
 assert_impl_all!(TypeParams<'static, AU16, IntoIter<()>>: FromZeroes);
 assert_impl_all!(TypeParams<'static, [AU16], IntoIter<()>>: FromZeroes);
+
+// Deriving `FromZeroes` should work if the struct has bounded parameters.
+
+#[derive(FromZeroes)]
+#[repr(transparent)]
+struct WithParams<'a: 'b, 'b: 'a, const N: usize, T: 'a + 'b + FromZeroes>(
+    [T; N],
+    PhantomData<&'a &'b ()>,
+)
+where
+    'a: 'b,
+    'b: 'a,
+    T: 'a + 'b + FromZeroes;
+
+assert_impl_all!(WithParams<'static, 'static, 42, u8>: FromZeroes);
diff --git a/tests/struct_known_layout.rs b/tests/struct_known_layout.rs
new file mode 100644
index 0000000..68d1284
--- /dev/null
+++ b/tests/struct_known_layout.rs
@@ -0,0 +1,65 @@
+// 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::{DstLayout, KnownLayout},
+};
+
+use crate::util::AU16;
+
+#[derive(KnownLayout)]
+struct Zst;
+
+assert_impl_all!(Zst: KnownLayout);
+
+#[derive(KnownLayout)]
+struct One {
+    a: bool,
+}
+
+assert_impl_all!(One: KnownLayout);
+
+#[derive(KnownLayout)]
+struct Two {
+    a: bool,
+    b: Zst,
+}
+
+assert_impl_all!(Two: KnownLayout);
+
+#[derive(KnownLayout)]
+struct TypeParams<'a, T, 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<()>>: KnownLayout);
+assert_impl_all!(TypeParams<'static, AU16, IntoIter<()>>: KnownLayout);
+
+// Deriving `KnownLayout` should work if the struct has bounded parameters.
+
+#[derive(KnownLayout)]
+#[repr(C)]
+struct WithParams<'a: 'b, 'b: 'a, const N: usize, T: 'a + 'b + KnownLayout>(
+    [T; N],
+    PhantomData<&'a &'b ()>,
+)
+where
+    'a: 'b,
+    'b: 'a,
+    T: 'a + 'b + KnownLayout;
+
+assert_impl_all!(WithParams<'static, 'static, 42, u8>: KnownLayout);
diff --git a/tests/struct_unaligned.rs b/tests/struct_unaligned.rs
index e843a0c..a7db432 100644
--- a/tests/struct_unaligned.rs
+++ b/tests/struct_unaligned.rs
@@ -1,6 +1,10 @@
-// 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.
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
 
 #![allow(warnings)]
 
@@ -79,3 +83,18 @@
 assert_impl_all!(TypeParams<'static, (), IntoIter<()>>: Unaligned);
 assert_impl_all!(TypeParams<'static, u8, IntoIter<()>>: Unaligned);
 assert_impl_all!(TypeParams<'static, [u8], IntoIter<()>>: Unaligned);
+
+// Deriving `Unaligned` should work if the struct has bounded parameters.
+
+#[derive(Unaligned)]
+#[repr(transparent)]
+struct WithParams<'a: 'b, 'b: 'a, const N: usize, T: 'a + 'b + Unaligned>(
+    [T; N],
+    PhantomData<&'a &'b ()>,
+)
+where
+    'a: 'b,
+    'b: 'a,
+    T: 'a + 'b + Unaligned;
+
+assert_impl_all!(WithParams<'static, 'static, 42, u8>: Unaligned);
diff --git a/tests/trybuild.rs b/tests/trybuild.rs
index 32f38cc..3ea1c3b 100644
--- a/tests/trybuild.rs
+++ b/tests/trybuild.rs
@@ -1,29 +1,19 @@
-// 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.
-
-// UI tests depend on the exact error messages emitted by rustc, but those error
-// messages are not stable, and sometimes change between Rust versions. Thus, we
-// maintain one set of UI tests for each Rust version that we test in CI, and we
-// 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-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::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.61.0)]
-const SOURCE_FILES_GLOB: &str = "tests/ui-msrv/*.rs";
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
 
 #[test]
+#[cfg_attr(miri, ignore)]
 fn ui() {
+    let version = testutil::ToolchainVersion::extract_from_pwd().unwrap();
+    // See the doc comment on this method for an explanation of what this does
+    // and why we store source files in different directories.
+    let source_files_dirname = version.get_ui_source_files_dirname_and_maybe_print_warning();
+
     let t = trybuild::TestCases::new();
-    t.compile_fail(SOURCE_FILES_GLOB);
+    t.compile_fail(format!("tests/{source_files_dirname}/*.rs"));
 }
diff --git a/tests/ui-msrv/derive_transparent.rs b/tests/ui-msrv/derive_transparent.rs
index a99f92c..2084d92 100644
--- a/tests/ui-msrv/derive_transparent.rs
+++ b/tests/ui-msrv/derive_transparent.rs
@@ -1,6 +1,10 @@
-// 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.
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
 
 extern crate zerocopy;
 
diff --git a/tests/ui-msrv/derive_transparent.stderr b/tests/ui-msrv/derive_transparent.stderr
index 3218446..3b228b1 100644
--- a/tests/ui-msrv/derive_transparent.stderr
+++ b/tests/ui-msrv/derive_transparent.stderr
@@ -1,71 +1,71 @@
 error[E0277]: the trait bound `NotZerocopy: FromZeroes` is not satisfied
-  --> tests/ui-msrv/derive_transparent.rs:33:1
+  --> tests/ui-msrv/derive_transparent.rs:37:1
    |
-33 | assert_impl_all!(TransparentStruct<NotZerocopy>: FromZeroes);
+37 | 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
+  --> tests/ui-msrv/derive_transparent.rs:27:19
    |
-23 | #[derive(AsBytes, FromZeroes, FromBytes, Unaligned)]
+27 | #[derive(AsBytes, FromZeroes, FromBytes, Unaligned)]
    |                   ^^^^^^^^^^
 note: required by a bound in `_::{closure#0}::assert_impl_all`
-  --> tests/ui-msrv/derive_transparent.rs:33:1
+  --> tests/ui-msrv/derive_transparent.rs:37:1
    |
-33 | assert_impl_all!(TransparentStruct<NotZerocopy>: FromZeroes);
+37 | 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
+  --> tests/ui-msrv/derive_transparent.rs:38:1
    |
-34 | assert_impl_all!(TransparentStruct<NotZerocopy>: FromBytes);
+38 | 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
+  --> tests/ui-msrv/derive_transparent.rs:27:31
    |
-23 | #[derive(AsBytes, FromZeroes, FromBytes, Unaligned)]
+27 | #[derive(AsBytes, FromZeroes, FromBytes, Unaligned)]
    |                               ^^^^^^^^^
 note: required by a bound in `_::{closure#0}::assert_impl_all`
-  --> tests/ui-msrv/derive_transparent.rs:34:1
+  --> tests/ui-msrv/derive_transparent.rs:38:1
    |
-34 | assert_impl_all!(TransparentStruct<NotZerocopy>: FromBytes);
+38 | 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
+  --> tests/ui-msrv/derive_transparent.rs:39:1
    |
-35 | assert_impl_all!(TransparentStruct<NotZerocopy>: AsBytes);
+39 | 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
+  --> tests/ui-msrv/derive_transparent.rs:27:10
    |
-23 | #[derive(AsBytes, FromZeroes, FromBytes, Unaligned)]
+27 | #[derive(AsBytes, FromZeroes, FromBytes, Unaligned)]
    |          ^^^^^^^
 note: required by a bound in `_::{closure#0}::assert_impl_all`
-  --> tests/ui-msrv/derive_transparent.rs:35:1
+  --> tests/ui-msrv/derive_transparent.rs:39:1
    |
-35 | assert_impl_all!(TransparentStruct<NotZerocopy>: AsBytes);
+39 | 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
+  --> tests/ui-msrv/derive_transparent.rs:40:1
    |
-36 | assert_impl_all!(TransparentStruct<NotZerocopy>: Unaligned);
+40 | 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
+  --> tests/ui-msrv/derive_transparent.rs:27:42
    |
-23 | #[derive(AsBytes, FromZeroes, FromBytes, Unaligned)]
+27 | #[derive(AsBytes, FromZeroes, FromBytes, Unaligned)]
    |                                          ^^^^^^^^^
 note: required by a bound in `_::{closure#0}::assert_impl_all`
-  --> tests/ui-msrv/derive_transparent.rs:36:1
+  --> tests/ui-msrv/derive_transparent.rs:40:1
    |
-36 | assert_impl_all!(TransparentStruct<NotZerocopy>: Unaligned);
+40 | 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 c3d1e27..31d5679 100644
--- a/tests/ui-msrv/enum.rs
+++ b/tests/ui-msrv/enum.rs
@@ -1,6 +1,10 @@
-// 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.
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
 
 #[macro_use]
 extern crate zerocopy;
diff --git a/tests/ui-msrv/enum.stderr b/tests/ui-msrv/enum.stderr
index a71b072..39bde3f 100644
--- a/tests/ui-msrv/enum.stderr
+++ b/tests/ui-msrv/enum.stderr
@@ -1,197 +1,197 @@
 error: unrecognized representation hint
-  --> tests/ui-msrv/enum.rs:15:8
+  --> tests/ui-msrv/enum.rs:19:8
    |
-15 | #[repr("foo")]
+19 | #[repr("foo")]
    |        ^^^^^
 
 error: unrecognized representation hint
-  --> tests/ui-msrv/enum.rs:21:8
+  --> tests/ui-msrv/enum.rs:25:8
    |
-21 | #[repr(foo)]
+25 | #[repr(foo)]
    |        ^^^
 
 error: unsupported representation for deriving FromBytes, AsBytes, or Unaligned on an enum
-  --> tests/ui-msrv/enum.rs:27:8
+  --> tests/ui-msrv/enum.rs:31:8
    |
-27 | #[repr(transparent)]
+31 | #[repr(transparent)]
    |        ^^^^^^^^^^^
 
 error: conflicting representation hints
-  --> tests/ui-msrv/enum.rs:33:1
+  --> tests/ui-msrv/enum.rs:37:1
    |
-33 | #[repr(u8, u16)]
+37 | #[repr(u8, u16)]
    | ^
 
 error: must have a non-align #[repr(...)] attribute in order to guarantee this type's memory layout
-  --> tests/ui-msrv/enum.rs:38:22
+  --> tests/ui-msrv/enum.rs:42:22
    |
-38 | #[derive(FromZeroes, FromBytes)]
+42 | #[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
+  --> tests/ui-msrv/enum.rs:52:1
    |
-48 | / enum FromZeroes1 {
-49 | |     A(u8),
-50 | | }
+52 | / enum FromZeroes1 {
+53 | |     A(u8),
+54 | | }
    | |_^
 
 error: only C-like enums can implement FromZeroes
-  --> tests/ui-msrv/enum.rs:53:1
+  --> tests/ui-msrv/enum.rs:57:1
    |
-53 | / enum FromZeroes2 {
-54 | |     A,
-55 | |     B(u8),
-56 | | }
+57 | / enum FromZeroes2 {
+58 | |     A,
+59 | |     B(u8),
+60 | | }
    | |_^
 
 error: FromZeroes only supported on enums with a variant that has a discriminant of `0`
-  --> tests/ui-msrv/enum.rs:59:1
+  --> tests/ui-msrv/enum.rs:63:1
    |
-59 | / enum FromZeroes3 {
-60 | |     A = 1,
-61 | |     B,
-62 | | }
+63 | / enum FromZeroes3 {
+64 | |     A = 1,
+65 | |     B,
+66 | | }
    | |_^
 
 error: FromBytes requires repr of "u8", "u16", "i8", or "i16"
-  --> tests/ui-msrv/enum.rs:69:8
+  --> tests/ui-msrv/enum.rs:73:8
    |
-69 | #[repr(C)]
+73 | #[repr(C)]
    |        ^
 
 error: FromBytes requires repr of "u8", "u16", "i8", or "i16"
-  --> tests/ui-msrv/enum.rs:75:8
+  --> tests/ui-msrv/enum.rs:79:8
    |
-75 | #[repr(usize)]
+79 | #[repr(usize)]
    |        ^^^^^
 
 error: FromBytes requires repr of "u8", "u16", "i8", or "i16"
-  --> tests/ui-msrv/enum.rs:81:8
+  --> tests/ui-msrv/enum.rs:85:8
    |
-81 | #[repr(isize)]
+85 | #[repr(isize)]
    |        ^^^^^
 
 error: FromBytes requires repr of "u8", "u16", "i8", or "i16"
-  --> tests/ui-msrv/enum.rs:87:8
+  --> tests/ui-msrv/enum.rs:91:8
    |
-87 | #[repr(u32)]
+91 | #[repr(u32)]
    |        ^^^
 
 error: FromBytes requires repr of "u8", "u16", "i8", or "i16"
-  --> tests/ui-msrv/enum.rs:93:8
+  --> tests/ui-msrv/enum.rs:97:8
    |
-93 | #[repr(i32)]
+97 | #[repr(i32)]
    |        ^^^
 
 error: FromBytes requires repr of "u8", "u16", "i8", or "i16"
-  --> tests/ui-msrv/enum.rs:99:8
-   |
-99 | #[repr(u64)]
-   |        ^^^
-
-error: FromBytes requires repr of "u8", "u16", "i8", or "i16"
-   --> tests/ui-msrv/enum.rs:105:8
+   --> tests/ui-msrv/enum.rs:103:8
     |
-105 | #[repr(i64)]
+103 | #[repr(u64)]
+    |        ^^^
+
+error: FromBytes requires repr of "u8", "u16", "i8", or "i16"
+   --> tests/ui-msrv/enum.rs:109:8
+    |
+109 | #[repr(i64)]
     |        ^^^
 
 error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
-   --> tests/ui-msrv/enum.rs:115:8
+   --> tests/ui-msrv/enum.rs:119:8
     |
-115 | #[repr(C)]
+119 | #[repr(C)]
     |        ^
 
 error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
-   --> tests/ui-msrv/enum.rs:121:8
+   --> tests/ui-msrv/enum.rs:125:8
     |
-121 | #[repr(u16)]
+125 | #[repr(u16)]
     |        ^^^
 
 error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
-   --> tests/ui-msrv/enum.rs:127:8
+   --> tests/ui-msrv/enum.rs:131:8
     |
-127 | #[repr(i16)]
+131 | #[repr(i16)]
     |        ^^^
 
 error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
-   --> tests/ui-msrv/enum.rs:133:8
+   --> tests/ui-msrv/enum.rs:137:8
     |
-133 | #[repr(u32)]
+137 | #[repr(u32)]
     |        ^^^
 
 error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
-   --> tests/ui-msrv/enum.rs:139:8
+   --> tests/ui-msrv/enum.rs:143:8
     |
-139 | #[repr(i32)]
+143 | #[repr(i32)]
     |        ^^^
 
 error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
-   --> tests/ui-msrv/enum.rs:145:8
+   --> tests/ui-msrv/enum.rs:149:8
     |
-145 | #[repr(u64)]
+149 | #[repr(u64)]
     |        ^^^
 
 error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
-   --> tests/ui-msrv/enum.rs:151:8
+   --> tests/ui-msrv/enum.rs:155:8
     |
-151 | #[repr(i64)]
+155 | #[repr(i64)]
     |        ^^^
 
 error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
-   --> tests/ui-msrv/enum.rs:157:8
+   --> tests/ui-msrv/enum.rs:161:8
     |
-157 | #[repr(usize)]
+161 | #[repr(usize)]
     |        ^^^^^
 
 error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
-   --> tests/ui-msrv/enum.rs:163:8
+   --> tests/ui-msrv/enum.rs:167:8
     |
-163 | #[repr(isize)]
+167 | #[repr(isize)]
     |        ^^^^^
 
 error: cannot derive Unaligned with repr(align(N > 1))
-   --> tests/ui-msrv/enum.rs:169:12
+   --> tests/ui-msrv/enum.rs:173:12
     |
-169 | #[repr(u8, align(2))]
+173 | #[repr(u8, align(2))]
     |            ^^^^^^^^
 
 error: cannot derive Unaligned with repr(align(N > 1))
-   --> tests/ui-msrv/enum.rs:175:12
+   --> tests/ui-msrv/enum.rs:179:12
     |
-175 | #[repr(i8, align(2))]
+179 | #[repr(i8, align(2))]
     |            ^^^^^^^^
 
 error: cannot derive Unaligned with repr(align(N > 1))
-   --> tests/ui-msrv/enum.rs:181:18
+   --> tests/ui-msrv/enum.rs:185:18
     |
-181 | #[repr(align(1), align(2))]
+185 | #[repr(align(1), align(2))]
     |                  ^^^^^^^^
 
 error: cannot derive Unaligned with repr(align(N > 1))
-   --> tests/ui-msrv/enum.rs:187:8
+   --> tests/ui-msrv/enum.rs:191:8
     |
-187 | #[repr(align(2), align(4))]
+191 | #[repr(align(2), align(4))]
     |        ^^^^^^^^
 
 error[E0565]: meta item in `repr` must be an identifier
-  --> tests/ui-msrv/enum.rs:15:8
+  --> tests/ui-msrv/enum.rs:19:8
    |
-15 | #[repr("foo")]
+19 | #[repr("foo")]
    |        ^^^^^
 
 error[E0552]: unrecognized representation hint
-  --> tests/ui-msrv/enum.rs:21:8
+  --> tests/ui-msrv/enum.rs:25:8
    |
-21 | #[repr(foo)]
+25 | #[repr(foo)]
    |        ^^^
 
 error[E0566]: conflicting representation hints
-  --> tests/ui-msrv/enum.rs:33:8
+  --> tests/ui-msrv/enum.rs:37:8
    |
-33 | #[repr(u8, u16)]
+37 | #[repr(u8, u16)]
    |        ^^  ^^^
    |
    = note: `#[deny(conflicting_repr_hints)]` on by default
diff --git a/tests/ui-msrv/enum_from_bytes_u8_too_few.rs b/tests/ui-msrv/enum_from_bytes_u8_too_few.rs
index 4f54ec7..1b1bed3 100644
--- a/tests/ui-msrv/enum_from_bytes_u8_too_few.rs
+++ b/tests/ui-msrv/enum_from_bytes_u8_too_few.rs
@@ -1,6 +1,10 @@
-// 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.
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
 
 #[macro_use]
 extern crate zerocopy;
diff --git a/tests/ui-msrv/enum_from_bytes_u8_too_few.stderr b/tests/ui-msrv/enum_from_bytes_u8_too_few.stderr
index c4e1bc6..ff828dc 100644
--- a/tests/ui-msrv/enum_from_bytes_u8_too_few.stderr
+++ b/tests/ui-msrv/enum_from_bytes_u8_too_few.stderr
@@ -1,11 +1,11 @@
 error: FromBytes only supported on repr(u8) enum with 256 variants
-   --> tests/ui-msrv/enum_from_bytes_u8_too_few.rs:11:1
+   --> tests/ui-msrv/enum_from_bytes_u8_too_few.rs:15:1
     |
-11  | / #[repr(u8)]
-12  | | enum Foo {
-13  | |     Variant0,
-14  | |     Variant1,
+15  | / #[repr(u8)]
+16  | | enum Foo {
+17  | |     Variant0,
+18  | |     Variant1,
 ...   |
-267 | |     Variant254,
-268 | | }
+271 | |     Variant254,
+272 | | }
     | |_^
diff --git a/tests/ui-msrv/late_compile_pass.rs b/tests/ui-msrv/late_compile_pass.rs
index 1b4c603..cd65a6e 100644
--- a/tests/ui-msrv/late_compile_pass.rs
+++ b/tests/ui-msrv/late_compile_pass.rs
@@ -1,6 +1,10 @@
-// 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.
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
 
 #[macro_use]
 extern crate zerocopy;
@@ -9,6 +13,7 @@
 mod util;
 
 use self::util::{NotZerocopy, AU16};
+use zerocopy::KnownLayout;
 
 fn main() {}
 
diff --git a/tests/ui-msrv/late_compile_pass.stderr b/tests/ui-msrv/late_compile_pass.stderr
index 29d20e4..39dbcd1 100644
--- a/tests/ui-msrv/late_compile_pass.stderr
+++ b/tests/ui-msrv/late_compile_pass.stderr
@@ -1,25 +1,33 @@
-error[E0277]: the trait bound `NotZerocopy: FromZeroes` is not satisfied
-  --> tests/ui-msrv/late_compile_pass.rs:23:10
+warning: unused import: `zerocopy::KnownLayout`
+  --> tests/ui-msrv/late_compile_pass.rs:16:5
    |
-23 | #[derive(FromZeroes)]
+16 | use zerocopy::KnownLayout;
+   |     ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(unused_imports)]` on by default
+
+error[E0277]: the trait bound `NotZerocopy: FromZeroes` is not satisfied
+  --> tests/ui-msrv/late_compile_pass.rs:28:10
+   |
+28 | #[derive(FromZeroes)]
    |          ^^^^^^^^^^ the trait `FromZeroes` is not implemented for `NotZerocopy`
    |
    = 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
+  --> tests/ui-msrv/late_compile_pass.rs:37:10
    |
-32 | #[derive(FromBytes)]
+37 | #[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 `FromBytes1: FromZeroes` is not satisfied
-  --> tests/ui-msrv/late_compile_pass.rs:32:10
+  --> tests/ui-msrv/late_compile_pass.rs:37:10
    |
-32 | #[derive(FromBytes)]
+37 | #[derive(FromBytes)]
    |          ^^^^^^^^^ the trait `FromZeroes` is not implemented for `FromBytes1`
    |
 note: required by a bound in `FromBytes`
@@ -30,36 +38,36 @@
    = 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-msrv/late_compile_pass.rs:41:10
+  --> tests/ui-msrv/late_compile_pass.rs:46:10
    |
-41 | #[derive(AsBytes)]
+46 | #[derive(AsBytes)]
    |          ^^^^^^^ the trait `AsBytes` is not implemented for `NotZerocopy`
    |
    = 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
+  --> tests/ui-msrv/late_compile_pass.rs:56:10
    |
-51 | #[derive(Unaligned)]
+56 | #[derive(Unaligned)]
    |          ^^^^^^^^^ the trait `Unaligned` is not implemented for `AU16`
    |
    = 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 `AU16: Unaligned` is not satisfied
-  --> tests/ui-msrv/late_compile_pass.rs:59:10
+  --> tests/ui-msrv/late_compile_pass.rs:64:10
    |
-59 | #[derive(Unaligned)]
+64 | #[derive(Unaligned)]
    |          ^^^^^^^^^ the trait `Unaligned` is not implemented for `AU16`
    |
    = 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 `AU16: Unaligned` is not satisfied
-  --> tests/ui-msrv/late_compile_pass.rs:66:10
+  --> tests/ui-msrv/late_compile_pass.rs:71:10
    |
-66 | #[derive(Unaligned)]
+71 | #[derive(Unaligned)]
    |          ^^^^^^^^^ the trait `Unaligned` is not implemented for `AU16`
    |
    = help: see issue #48214
diff --git a/tests/ui-msrv/mid_compile_pass.rs b/tests/ui-msrv/mid_compile_pass.rs
new file mode 100644
index 0000000..e0c4bc5
--- /dev/null
+++ b/tests/ui-msrv/mid_compile_pass.rs
@@ -0,0 +1,61 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::KnownLayout;
+
+fn main() {}
+
+// These tests cause errors which are generated by a later compilation pass than
+// the other errors we generate, and so if they're compiled in the same file,
+// the compiler will never get to that pass, and so we won't get the errors.
+
+//
+// KnownLayout errors
+//
+
+fn assert_kl<T: ?Sized + KnownLayout>(_: &T) {}
+
+// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+// |          N |        Y |              N |        N |      KL04 |
+#[derive(KnownLayout)]
+struct KL04<T: ?Sized>(u8, T);
+
+fn test_kl04<T: ?Sized>(kl: &KL04<T>) {
+    assert_kl(kl);
+}
+
+// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+// |          N |        Y |              Y |        N |      KL06 |
+#[derive(KnownLayout)]
+struct KL06<T: ?Sized + KnownLayout>(u8, T);
+
+fn test_kl06<T: ?Sized + KnownLayout>(kl: &KL06<T>) {
+    assert_kl(kl);
+}
+
+// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+// |          Y |        Y |              N |        N |      KL12 |
+#[derive(KnownLayout)]
+#[repr(C)]
+struct KL12<T: ?Sized>(u8, T);
+
+fn test_kl12<T: ?Sized>(kl: &KL12<T>) {
+    assert_kl(kl)
+}
+
+// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+// |          Y |        Y |              N |        Y |      KL13 |
+#[derive(KnownLayout)]
+#[repr(C)]
+struct KL13<T>(u8, T);
+
+fn test_kl13<T>(t: T) -> impl KnownLayout {
+    KL13(0u8, t)
+}
diff --git a/tests/ui-msrv/mid_compile_pass.stderr b/tests/ui-msrv/mid_compile_pass.stderr
new file mode 100644
index 0000000..5aa2cde
--- /dev/null
+++ b/tests/ui-msrv/mid_compile_pass.stderr
@@ -0,0 +1,104 @@
+error[E0277]: the trait bound `T: KnownLayout` is not satisfied
+  --> tests/ui-msrv/mid_compile_pass.rs:59:26
+   |
+59 | fn test_kl13<T>(t: T) -> impl KnownLayout {
+   |                          ^^^^^^^^^^^^^^^^ the trait `KnownLayout` is not implemented for `T`
+   |
+note: required because of the requirements on the impl of `KnownLayout` for `KL13<T>`
+  --> tests/ui-msrv/mid_compile_pass.rs:55:10
+   |
+55 | #[derive(KnownLayout)]
+   |          ^^^^^^^^^^^
+   = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider restricting type parameter `T`
+   |
+59 | fn test_kl13<T: zerocopy::KnownLayout>(t: T) -> impl KnownLayout {
+   |               +++++++++++++++++++++++
+
+error[E0277]: the size for values of type `T` cannot be known at compilation time
+  --> tests/ui-msrv/mid_compile_pass.rs:31:15
+   |
+30 | fn test_kl04<T: ?Sized>(kl: &KL04<T>) {
+   |              - this type parameter needs to be `std::marker::Sized`
+31 |     assert_kl(kl);
+   |     --------- ^^ doesn't have a size known at compile-time
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required because it appears within the type `KL04<T>`
+  --> tests/ui-msrv/mid_compile_pass.rs:28:8
+   |
+28 | struct KL04<T: ?Sized>(u8, T);
+   |        ^^^^
+note: required because of the requirements on the impl of `KnownLayout` for `KL04<T>`
+  --> tests/ui-msrv/mid_compile_pass.rs:27:10
+   |
+27 | #[derive(KnownLayout)]
+   |          ^^^^^^^^^^^
+note: required by a bound in `assert_kl`
+  --> tests/ui-msrv/mid_compile_pass.rs:23:26
+   |
+23 | fn assert_kl<T: ?Sized + KnownLayout>(_: &T) {}
+   |                          ^^^^^^^^^^^ required by this bound in `assert_kl`
+   = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+   |
+30 - fn test_kl04<T: ?Sized>(kl: &KL04<T>) {
+30 + fn test_kl04<T>(kl: &KL04<T>) {
+   |
+
+error[E0277]: the size for values of type `T` cannot be known at compilation time
+  --> tests/ui-msrv/mid_compile_pass.rs:40:15
+   |
+39 | fn test_kl06<T: ?Sized + KnownLayout>(kl: &KL06<T>) {
+   |              - this type parameter needs to be `std::marker::Sized`
+40 |     assert_kl(kl);
+   |     --------- ^^ doesn't have a size known at compile-time
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required because it appears within the type `KL06<T>`
+  --> tests/ui-msrv/mid_compile_pass.rs:37:8
+   |
+37 | struct KL06<T: ?Sized + KnownLayout>(u8, T);
+   |        ^^^^
+note: required because of the requirements on the impl of `KnownLayout` for `KL06<T>`
+  --> tests/ui-msrv/mid_compile_pass.rs:36:10
+   |
+36 | #[derive(KnownLayout)]
+   |          ^^^^^^^^^^^
+note: required by a bound in `assert_kl`
+  --> tests/ui-msrv/mid_compile_pass.rs:23:26
+   |
+23 | fn assert_kl<T: ?Sized + KnownLayout>(_: &T) {}
+   |                          ^^^^^^^^^^^ required by this bound in `assert_kl`
+   = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+   |
+39 - fn test_kl06<T: ?Sized + KnownLayout>(kl: &KL06<T>) {
+39 + fn test_kl06<T: KnownLayout>(kl: &KL06<T>) {
+   |
+
+error[E0277]: the trait bound `T: KnownLayout` is not satisfied
+  --> tests/ui-msrv/mid_compile_pass.rs:50:15
+   |
+50 |     assert_kl(kl)
+   |     --------- ^^ the trait `KnownLayout` is not implemented for `T`
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required because of the requirements on the impl of `KnownLayout` for `KL12<T>`
+  --> tests/ui-msrv/mid_compile_pass.rs:45:10
+   |
+45 | #[derive(KnownLayout)]
+   |          ^^^^^^^^^^^
+note: required by a bound in `assert_kl`
+  --> tests/ui-msrv/mid_compile_pass.rs:23:26
+   |
+23 | fn assert_kl<T: ?Sized + KnownLayout>(_: &T) {}
+   |                          ^^^^^^^^^^^ required by this bound in `assert_kl`
+   = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider further restricting this bound
+   |
+49 | fn test_kl12<T: ?Sized + zerocopy::KnownLayout>(kl: &KL12<T>) {
+   |                        +++++++++++++++++++++++
diff --git a/tests/ui-msrv/struct.rs b/tests/ui-msrv/struct.rs
index 29aa0e8..c76dc7f 100644
--- a/tests/ui-msrv/struct.rs
+++ b/tests/ui-msrv/struct.rs
@@ -1,6 +1,10 @@
-// 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.
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
 
 #[macro_use]
 extern crate zerocopy;
@@ -8,11 +12,43 @@
 #[path = "../util.rs"]
 mod util;
 
+use zerocopy::KnownLayout;
+
 use self::util::AU16;
 
 fn main() {}
 
 //
+// KnownLayout errors
+//
+
+struct NotKnownLayout;
+
+struct NotKnownLayoutDst([u8]);
+
+// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+// |          N |        N |              N |        N |      KL00 |
+#[derive(KnownLayout)]
+struct KL00(u8, NotKnownLayoutDst);
+
+// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+// |          N |        N |              Y |        N |      KL02 |
+#[derive(KnownLayout)]
+struct KL02(u8, [u8]);
+
+// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+// |          Y |        N |              N |        N |      KL08 |
+#[derive(KnownLayout)]
+#[repr(C)]
+struct KL08(u8, NotKnownLayoutDst);
+
+// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+// |          Y |        N |              N |        Y |      KL09 |
+#[derive(KnownLayout)]
+#[repr(C)]
+struct KL09(NotKnownLayout, NotKnownLayout);
+
+//
 // AsBytes errors
 //
 
@@ -27,6 +63,15 @@
     bar: AU16,
 }
 
+#[derive(AsBytes)]
+#[repr(C, packed(2))]
+struct AsBytes3 {
+    foo: u8,
+    // We'd prefer to use AU64 here, but you can't use aligned types in
+    // packed structs.
+    bar: u64,
+}
+
 //
 // Unaligned errors
 //
diff --git a/tests/ui-msrv/struct.stderr b/tests/ui-msrv/struct.stderr
index fe73b80..f4a435d 100644
--- a/tests/ui-msrv/struct.stderr
+++ b/tests/ui-msrv/struct.stderr
@@ -1,54 +1,113 @@
 error: unsupported on generic structs that are not repr(transparent) or repr(packed)
-  --> tests/ui-msrv/struct.rs:19:10
+  --> tests/ui-msrv/struct.rs:55:10
    |
-19 | #[derive(AsBytes)]
+55 | #[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:35:11
+  --> tests/ui-msrv/struct.rs:80:11
    |
-35 | #[repr(C, align(2))]
+80 | #[repr(C, align(2))]
    |           ^^^^^^^^
 
 error: cannot derive Unaligned with repr(align(N > 1))
-  --> tests/ui-msrv/struct.rs:39:21
+  --> tests/ui-msrv/struct.rs:84:21
    |
-39 | #[repr(transparent, align(2))]
+84 | #[repr(transparent, align(2))]
    |                     ^^^^^^^^
 
 error: cannot derive Unaligned with repr(align(N > 1))
-  --> tests/ui-msrv/struct.rs:45:16
+  --> tests/ui-msrv/struct.rs:90:16
    |
-45 | #[repr(packed, align(2))]
+90 | #[repr(packed, align(2))]
    |                ^^^^^^^^
 
 error: cannot derive Unaligned with repr(align(N > 1))
-  --> tests/ui-msrv/struct.rs:49:18
+  --> tests/ui-msrv/struct.rs:94:18
    |
-49 | #[repr(align(1), align(2))]
+94 | #[repr(align(1), align(2))]
    |                  ^^^^^^^^
 
 error: cannot derive Unaligned with repr(align(N > 1))
-  --> tests/ui-msrv/struct.rs:53:8
+  --> tests/ui-msrv/struct.rs:98:8
    |
-53 | #[repr(align(2), align(4))]
+98 | #[repr(align(2), align(4))]
    |        ^^^^^^^^
 
 error[E0692]: transparent struct cannot have other repr hints
-  --> tests/ui-msrv/struct.rs:39:8
+  --> tests/ui-msrv/struct.rs:84:8
    |
-39 | #[repr(transparent, align(2))]
+84 | #[repr(transparent, align(2))]
    |        ^^^^^^^^^^^  ^^^^^^^^
 
-error[E0277]: the trait bound `HasPadding<AsBytes2, true>: ShouldBe<false>` is not satisfied
-  --> tests/ui-msrv/struct.rs:23:10
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> tests/ui-msrv/struct.rs:31:10
    |
-23 | #[derive(AsBytes)]
+31 | #[derive(KnownLayout)]
+   |          ^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: within `KL00`, the trait `Sized` is not implemented for `[u8]`
+note: required because it appears within the type `KL00`
+  --> tests/ui-msrv/struct.rs:32:8
+   |
+32 | struct KL00(u8, NotKnownLayoutDst);
+   |        ^^^^
+   = help: see issue #48214
+   = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> tests/ui-msrv/struct.rs:36:10
+   |
+36 | #[derive(KnownLayout)]
+   |          ^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: within `KL02`, the trait `Sized` is not implemented for `[u8]`
+note: required because it appears within the type `KL02`
+  --> tests/ui-msrv/struct.rs:37:8
+   |
+37 | struct KL02(u8, [u8]);
+   |        ^^^^
+   = help: see issue #48214
+   = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `NotKnownLayoutDst: KnownLayout` is not satisfied
+  --> tests/ui-msrv/struct.rs:41:10
+   |
+41 | #[derive(KnownLayout)]
+   |          ^^^^^^^^^^^ the trait `KnownLayout` is not implemented for `NotKnownLayoutDst`
+   |
+   = help: see issue #48214
+   = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `NotKnownLayout: KnownLayout` is not satisfied
+  --> tests/ui-msrv/struct.rs:47:10
+   |
+47 | #[derive(KnownLayout)]
+   |          ^^^^^^^^^^^ the trait `KnownLayout` is not implemented for `NotKnownLayout`
+   |
+   = help: see issue #48214
+   = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `HasPadding<AsBytes2, true>: ShouldBe<false>` is not satisfied
+  --> tests/ui-msrv/struct.rs:59:10
+   |
+59 | #[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)
+
+error[E0277]: the trait bound `HasPadding<AsBytes3, true>: ShouldBe<false>` is not satisfied
+  --> tests/ui-msrv/struct.rs:66:10
+   |
+66 | #[derive(AsBytes)]
+   |          ^^^^^^^ the trait `ShouldBe<false>` is not implemented for `HasPadding<AsBytes3, 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 e7761e0..8938e78 100644
--- a/tests/ui-msrv/union.rs
+++ b/tests/ui-msrv/union.rs
@@ -1,6 +1,10 @@
-// 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.
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
 
 #[macro_use]
 extern crate zerocopy;
diff --git a/tests/ui-msrv/union.stderr b/tests/ui-msrv/union.stderr
index 711b8e2..3e13059 100644
--- a/tests/ui-msrv/union.stderr
+++ b/tests/ui-msrv/union.stderr
@@ -1,39 +1,39 @@
 error: unsupported on types with type parameters
-  --> tests/ui-msrv/union.rs:20:10
+  --> tests/ui-msrv/union.rs:24:10
    |
-20 | #[derive(AsBytes)]
+24 | #[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:38:11
+  --> tests/ui-msrv/union.rs:42:11
    |
-38 | #[repr(C, align(2))]
+42 | #[repr(C, align(2))]
    |           ^^^^^^^^
 
 error: cannot derive Unaligned with repr(align(N > 1))
-  --> tests/ui-msrv/union.rs:54:16
+  --> tests/ui-msrv/union.rs:58:16
    |
-54 | #[repr(packed, align(2))]
+58 | #[repr(packed, align(2))]
    |                ^^^^^^^^
 
 error: cannot derive Unaligned with repr(align(N > 1))
-  --> tests/ui-msrv/union.rs:60:18
+  --> tests/ui-msrv/union.rs:64:18
    |
-60 | #[repr(align(1), align(2))]
+64 | #[repr(align(1), align(2))]
    |                  ^^^^^^^^
 
 error: cannot derive Unaligned with repr(align(N > 1))
-  --> tests/ui-msrv/union.rs:66:8
+  --> tests/ui-msrv/union.rs:70:8
    |
-66 | #[repr(align(2), align(4))]
+70 | #[repr(align(2), align(4))]
    |        ^^^^^^^^
 
 error[E0277]: the trait bound `HasPadding<AsBytes2, true>: ShouldBe<false>` is not satisfied
-  --> tests/ui-msrv/union.rs:26:10
+  --> tests/ui-msrv/union.rs:30:10
    |
-26 | #[derive(AsBytes)]
+30 | #[derive(AsBytes)]
    |          ^^^^^^^ the trait `ShouldBe<false>` is not implemented for `HasPadding<AsBytes2, true>`
    |
    = help: the following implementations were found:
diff --git a/tests/ui-nightly/derive_transparent.rs b/tests/ui-nightly/derive_transparent.rs
index a99f92c..2084d92 100644
--- a/tests/ui-nightly/derive_transparent.rs
+++ b/tests/ui-nightly/derive_transparent.rs
@@ -1,6 +1,10 @@
-// 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.
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
 
 extern crate zerocopy;
 
diff --git a/tests/ui-nightly/derive_transparent.stderr b/tests/ui-nightly/derive_transparent.stderr
index 5a7d507..f214877 100644
--- a/tests/ui-nightly/derive_transparent.stderr
+++ b/tests/ui-nightly/derive_transparent.stderr
@@ -1,111 +1,111 @@
 error[E0277]: the trait bound `NotZerocopy: FromZeroes` is not satisfied
-  --> tests/ui-nightly/derive_transparent.rs:33:18
+  --> tests/ui-nightly/derive_transparent.rs:37:18
    |
-33 | assert_impl_all!(TransparentStruct<NotZerocopy>: FromZeroes);
+37 | 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>
+             bool
+             char
+             isize
+             i8
+             i16
+             i32
+             i64
+             i128
            and $N others
 note: required for `TransparentStruct<NotZerocopy>` to implement `FromZeroes`
-  --> tests/ui-nightly/derive_transparent.rs:23:19
+  --> tests/ui-nightly/derive_transparent.rs:27:19
    |
-23 | #[derive(AsBytes, FromZeroes, FromBytes, Unaligned)]
+27 | #[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
+  --> tests/ui-nightly/derive_transparent.rs:37:1
    |
-33 | assert_impl_all!(TransparentStruct<NotZerocopy>: FromZeroes);
+37 | 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
+  --> tests/ui-nightly/derive_transparent.rs:38:18
    |
-34 | assert_impl_all!(TransparentStruct<NotZerocopy>: FromBytes);
+38 | 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>
+             isize
+             i8
+             i16
+             i32
+             i64
+             i128
+             usize
+             u8
            and $N others
 note: required for `TransparentStruct<NotZerocopy>` to implement `FromBytes`
-  --> tests/ui-nightly/derive_transparent.rs:23:31
+  --> tests/ui-nightly/derive_transparent.rs:27:31
    |
-23 | #[derive(AsBytes, FromZeroes, FromBytes, Unaligned)]
+27 | #[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
+  --> tests/ui-nightly/derive_transparent.rs:38:1
    |
-34 | assert_impl_all!(TransparentStruct<NotZerocopy>: FromBytes);
+38 | 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
+  --> tests/ui-nightly/derive_transparent.rs:39:18
    |
-35 | assert_impl_all!(TransparentStruct<NotZerocopy>: AsBytes);
+39 | 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>
+             bool
+             char
+             isize
+             i8
+             i16
+             i32
+             i64
+             i128
            and $N others
 note: required for `TransparentStruct<NotZerocopy>` to implement `AsBytes`
-  --> tests/ui-nightly/derive_transparent.rs:23:10
+  --> tests/ui-nightly/derive_transparent.rs:27:10
    |
-23 | #[derive(AsBytes, FromZeroes, FromBytes, Unaligned)]
+27 | #[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
+  --> tests/ui-nightly/derive_transparent.rs:39:1
    |
-35 | assert_impl_all!(TransparentStruct<NotZerocopy>: AsBytes);
+39 | 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
+  --> tests/ui-nightly/derive_transparent.rs:40:18
    |
-36 | assert_impl_all!(TransparentStruct<NotZerocopy>: Unaligned);
+40 | 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>
+             bool
+             i8
+             u8
+             TransparentStruct<T>
+             U16<O>
+             U32<O>
+             U64<O>
+             U128<O>
            and $N others
 note: required for `TransparentStruct<NotZerocopy>` to implement `Unaligned`
-  --> tests/ui-nightly/derive_transparent.rs:23:42
+  --> tests/ui-nightly/derive_transparent.rs:27:42
    |
-23 | #[derive(AsBytes, FromZeroes, FromBytes, Unaligned)]
+27 | #[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
+  --> tests/ui-nightly/derive_transparent.rs:40:1
    |
-36 | assert_impl_all!(TransparentStruct<NotZerocopy>: Unaligned);
+40 | 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-nightly/enum.rs b/tests/ui-nightly/enum.rs
index c3d1e27..31d5679 100644
--- a/tests/ui-nightly/enum.rs
+++ b/tests/ui-nightly/enum.rs
@@ -1,6 +1,10 @@
-// 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.
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
 
 #[macro_use]
 extern crate zerocopy;
diff --git a/tests/ui-nightly/enum.stderr b/tests/ui-nightly/enum.stderr
index 0c291b5..a4d5edf 100644
--- a/tests/ui-nightly/enum.stderr
+++ b/tests/ui-nightly/enum.stderr
@@ -1,199 +1,199 @@
 error: unrecognized representation hint
-  --> tests/ui-nightly/enum.rs:15:8
+  --> tests/ui-nightly/enum.rs:19:8
    |
-15 | #[repr("foo")]
+19 | #[repr("foo")]
    |        ^^^^^
 
 error: unrecognized representation hint
-  --> tests/ui-nightly/enum.rs:21:8
+  --> tests/ui-nightly/enum.rs:25:8
    |
-21 | #[repr(foo)]
+25 | #[repr(foo)]
    |        ^^^
 
 error: unsupported representation for deriving FromBytes, AsBytes, or Unaligned on an enum
-  --> tests/ui-nightly/enum.rs:27:8
+  --> tests/ui-nightly/enum.rs:31:8
    |
-27 | #[repr(transparent)]
+31 | #[repr(transparent)]
    |        ^^^^^^^^^^^
 
 error: conflicting representation hints
-  --> tests/ui-nightly/enum.rs:33:8
+  --> tests/ui-nightly/enum.rs:37:8
    |
-33 | #[repr(u8, u16)]
+37 | #[repr(u8, u16)]
    |        ^^^^^^^
 
 error: must have a non-align #[repr(...)] attribute in order to guarantee this type's memory layout
-  --> tests/ui-nightly/enum.rs:38:22
+  --> tests/ui-nightly/enum.rs:42:22
    |
-38 | #[derive(FromZeroes, FromBytes)]
+42 | #[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
+  --> tests/ui-nightly/enum.rs:52:1
    |
-48 | / enum FromZeroes1 {
-49 | |     A(u8),
-50 | | }
+52 | / enum FromZeroes1 {
+53 | |     A(u8),
+54 | | }
    | |_^
 
 error: only C-like enums can implement FromZeroes
-  --> tests/ui-nightly/enum.rs:53:1
+  --> tests/ui-nightly/enum.rs:57:1
    |
-53 | / enum FromZeroes2 {
-54 | |     A,
-55 | |     B(u8),
-56 | | }
+57 | / enum FromZeroes2 {
+58 | |     A,
+59 | |     B(u8),
+60 | | }
    | |_^
 
 error: FromZeroes only supported on enums with a variant that has a discriminant of `0`
-  --> tests/ui-nightly/enum.rs:59:1
+  --> tests/ui-nightly/enum.rs:63:1
    |
-59 | / enum FromZeroes3 {
-60 | |     A = 1,
-61 | |     B,
-62 | | }
+63 | / enum FromZeroes3 {
+64 | |     A = 1,
+65 | |     B,
+66 | | }
    | |_^
 
 error: FromBytes requires repr of "u8", "u16", "i8", or "i16"
-  --> tests/ui-nightly/enum.rs:69:8
+  --> tests/ui-nightly/enum.rs:73:8
    |
-69 | #[repr(C)]
+73 | #[repr(C)]
    |        ^
 
 error: FromBytes requires repr of "u8", "u16", "i8", or "i16"
-  --> tests/ui-nightly/enum.rs:75:8
+  --> tests/ui-nightly/enum.rs:79:8
    |
-75 | #[repr(usize)]
+79 | #[repr(usize)]
    |        ^^^^^
 
 error: FromBytes requires repr of "u8", "u16", "i8", or "i16"
-  --> tests/ui-nightly/enum.rs:81:8
+  --> tests/ui-nightly/enum.rs:85:8
    |
-81 | #[repr(isize)]
+85 | #[repr(isize)]
    |        ^^^^^
 
 error: FromBytes requires repr of "u8", "u16", "i8", or "i16"
-  --> tests/ui-nightly/enum.rs:87:8
+  --> tests/ui-nightly/enum.rs:91:8
    |
-87 | #[repr(u32)]
+91 | #[repr(u32)]
    |        ^^^
 
 error: FromBytes requires repr of "u8", "u16", "i8", or "i16"
-  --> tests/ui-nightly/enum.rs:93:8
+  --> tests/ui-nightly/enum.rs:97:8
    |
-93 | #[repr(i32)]
+97 | #[repr(i32)]
    |        ^^^
 
 error: FromBytes requires repr of "u8", "u16", "i8", or "i16"
-  --> tests/ui-nightly/enum.rs:99:8
-   |
-99 | #[repr(u64)]
-   |        ^^^
-
-error: FromBytes requires repr of "u8", "u16", "i8", or "i16"
-   --> tests/ui-nightly/enum.rs:105:8
+   --> tests/ui-nightly/enum.rs:103:8
     |
-105 | #[repr(i64)]
+103 | #[repr(u64)]
+    |        ^^^
+
+error: FromBytes requires repr of "u8", "u16", "i8", or "i16"
+   --> tests/ui-nightly/enum.rs:109:8
+    |
+109 | #[repr(i64)]
     |        ^^^
 
 error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
-   --> tests/ui-nightly/enum.rs:115:8
+   --> tests/ui-nightly/enum.rs:119:8
     |
-115 | #[repr(C)]
+119 | #[repr(C)]
     |        ^
 
 error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
-   --> tests/ui-nightly/enum.rs:121:8
+   --> tests/ui-nightly/enum.rs:125:8
     |
-121 | #[repr(u16)]
+125 | #[repr(u16)]
     |        ^^^
 
 error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
-   --> tests/ui-nightly/enum.rs:127:8
+   --> tests/ui-nightly/enum.rs:131:8
     |
-127 | #[repr(i16)]
+131 | #[repr(i16)]
     |        ^^^
 
 error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
-   --> tests/ui-nightly/enum.rs:133:8
+   --> tests/ui-nightly/enum.rs:137:8
     |
-133 | #[repr(u32)]
+137 | #[repr(u32)]
     |        ^^^
 
 error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
-   --> tests/ui-nightly/enum.rs:139:8
+   --> tests/ui-nightly/enum.rs:143:8
     |
-139 | #[repr(i32)]
+143 | #[repr(i32)]
     |        ^^^
 
 error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
-   --> tests/ui-nightly/enum.rs:145:8
+   --> tests/ui-nightly/enum.rs:149:8
     |
-145 | #[repr(u64)]
+149 | #[repr(u64)]
     |        ^^^
 
 error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
-   --> tests/ui-nightly/enum.rs:151:8
+   --> tests/ui-nightly/enum.rs:155:8
     |
-151 | #[repr(i64)]
+155 | #[repr(i64)]
     |        ^^^
 
 error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
-   --> tests/ui-nightly/enum.rs:157:8
+   --> tests/ui-nightly/enum.rs:161:8
     |
-157 | #[repr(usize)]
+161 | #[repr(usize)]
     |        ^^^^^
 
 error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
-   --> tests/ui-nightly/enum.rs:163:8
+   --> tests/ui-nightly/enum.rs:167:8
     |
-163 | #[repr(isize)]
+167 | #[repr(isize)]
     |        ^^^^^
 
 error: cannot derive Unaligned with repr(align(N > 1))
-   --> tests/ui-nightly/enum.rs:169:12
+   --> tests/ui-nightly/enum.rs:173:12
     |
-169 | #[repr(u8, align(2))]
+173 | #[repr(u8, align(2))]
     |            ^^^^^^^^
 
 error: cannot derive Unaligned with repr(align(N > 1))
-   --> tests/ui-nightly/enum.rs:175:12
+   --> tests/ui-nightly/enum.rs:179:12
     |
-175 | #[repr(i8, align(2))]
+179 | #[repr(i8, align(2))]
     |            ^^^^^^^^
 
 error: cannot derive Unaligned with repr(align(N > 1))
-   --> tests/ui-nightly/enum.rs:181:18
+   --> tests/ui-nightly/enum.rs:185:18
     |
-181 | #[repr(align(1), align(2))]
+185 | #[repr(align(1), align(2))]
     |                  ^^^^^^^^
 
 error: cannot derive Unaligned with repr(align(N > 1))
-   --> tests/ui-nightly/enum.rs:187:8
+   --> tests/ui-nightly/enum.rs:191:8
     |
-187 | #[repr(align(2), align(4))]
+191 | #[repr(align(2), align(4))]
     |        ^^^^^^^^
 
 error[E0565]: meta item in `repr` must be an identifier
-  --> tests/ui-nightly/enum.rs:15:8
+  --> tests/ui-nightly/enum.rs:19:8
    |
-15 | #[repr("foo")]
+19 | #[repr("foo")]
    |        ^^^^^
 
 error[E0552]: unrecognized representation hint
-  --> tests/ui-nightly/enum.rs:21:8
+  --> tests/ui-nightly/enum.rs:25:8
    |
-21 | #[repr(foo)]
+25 | #[repr(foo)]
    |        ^^^
    |
-   = help: valid reprs are `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize`
+   = help: valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize`
 
 error[E0566]: conflicting representation hints
-  --> tests/ui-nightly/enum.rs:33:8
+  --> tests/ui-nightly/enum.rs:37:8
    |
-33 | #[repr(u8, u16)]
+37 | #[repr(u8, u16)]
    |        ^^  ^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
diff --git a/tests/ui-nightly/enum_from_bytes_u16_too_few.rs.disabled b/tests/ui-nightly/enum_from_bytes_u16_too_few.rs.disabled
index 99bc764..e930130 100644
--- a/tests/ui-nightly/enum_from_bytes_u16_too_few.rs.disabled
+++ b/tests/ui-nightly/enum_from_bytes_u16_too_few.rs.disabled
@@ -1,6 +1,10 @@
-// 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.
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
 
 #[macro_use]
 extern crate zerocopy;
diff --git a/tests/ui-nightly/enum_from_bytes_u8_too_few.rs b/tests/ui-nightly/enum_from_bytes_u8_too_few.rs
index 4f54ec7..1b1bed3 100644
--- a/tests/ui-nightly/enum_from_bytes_u8_too_few.rs
+++ b/tests/ui-nightly/enum_from_bytes_u8_too_few.rs
@@ -1,6 +1,10 @@
-// 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.
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
 
 #[macro_use]
 extern crate zerocopy;
diff --git a/tests/ui-nightly/enum_from_bytes_u8_too_few.stderr b/tests/ui-nightly/enum_from_bytes_u8_too_few.stderr
index 1ecba21..50cf0e7 100644
--- a/tests/ui-nightly/enum_from_bytes_u8_too_few.stderr
+++ b/tests/ui-nightly/enum_from_bytes_u8_too_few.stderr
@@ -1,11 +1,11 @@
 error: FromBytes only supported on repr(u8) enum with 256 variants
-   --> tests/ui-nightly/enum_from_bytes_u8_too_few.rs:11:1
+   --> tests/ui-nightly/enum_from_bytes_u8_too_few.rs:15:1
     |
-11  | / #[repr(u8)]
-12  | | enum Foo {
-13  | |     Variant0,
-14  | |     Variant1,
+15  | / #[repr(u8)]
+16  | | enum Foo {
+17  | |     Variant0,
+18  | |     Variant1,
 ...   |
-267 | |     Variant254,
-268 | | }
+271 | |     Variant254,
+272 | | }
     | |_^
diff --git a/tests/ui-nightly/late_compile_pass.rs b/tests/ui-nightly/late_compile_pass.rs
index 1b4c603..cd65a6e 100644
--- a/tests/ui-nightly/late_compile_pass.rs
+++ b/tests/ui-nightly/late_compile_pass.rs
@@ -1,6 +1,10 @@
-// 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.
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
 
 #[macro_use]
 extern crate zerocopy;
@@ -9,6 +13,7 @@
 mod util;
 
 use self::util::{NotZerocopy, AU16};
+use zerocopy::KnownLayout;
 
 fn main() {}
 
diff --git a/tests/ui-nightly/late_compile_pass.stderr b/tests/ui-nightly/late_compile_pass.stderr
index fbf9da7..3c45dc4 100644
--- a/tests/ui-nightly/late_compile_pass.stderr
+++ b/tests/ui-nightly/late_compile_pass.stderr
@@ -1,58 +1,66 @@
-error[E0277]: the trait bound `NotZerocopy: FromZeroes` is not satisfied
-  --> tests/ui-nightly/late_compile_pass.rs:23:10
+warning: unused import: `zerocopy::KnownLayout`
+  --> tests/ui-nightly/late_compile_pass.rs:16:5
    |
-23 | #[derive(FromZeroes)]
+16 | use zerocopy::KnownLayout;
+   |     ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(unused_imports)]` on by default
+
+error[E0277]: the trait bound `NotZerocopy: FromZeroes` is not satisfied
+  --> tests/ui-nightly/late_compile_pass.rs:28:10
+   |
+28 | #[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>
+             bool
+             char
+             isize
+             i8
+             i16
+             i32
+             i64
+             i128
            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
+  --> tests/ui-nightly/late_compile_pass.rs:37:10
    |
-32 | #[derive(FromBytes)]
+37 | #[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>
+             isize
+             i8
+             i16
+             i32
+             i64
+             i128
+             usize
+             u8
            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
+  --> tests/ui-nightly/late_compile_pass.rs:37:10
    |
-32 | #[derive(FromBytes)]
+37 | #[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>
+             bool
+             char
+             isize
+             i8
+             i16
+             i32
+             i64
+             i128
            and $N others
 note: required by a bound in `FromBytes`
   --> $WORKSPACE/src/lib.rs
@@ -62,80 +70,80 @@
    = 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
+  --> tests/ui-nightly/late_compile_pass.rs:46:10
    |
-41 | #[derive(AsBytes)]
+46 | #[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>
+             bool
+             char
+             isize
+             i8
+             i16
+             i32
+             i64
+             i128
            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
+  --> tests/ui-nightly/late_compile_pass.rs:56:10
    |
-51 | #[derive(Unaligned)]
+56 | #[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>
+             bool
+             i8
+             u8
+             Unaligned1
+             Unaligned2
+             Unaligned3
+             U16<O>
+             U32<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 `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
+  --> tests/ui-nightly/late_compile_pass.rs:64:10
    |
-59 | #[derive(Unaligned)]
+64 | #[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>
+             bool
+             i8
+             u8
+             Unaligned1
+             Unaligned2
+             Unaligned3
+             U16<O>
+             U32<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 `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
+  --> tests/ui-nightly/late_compile_pass.rs:71:10
    |
-66 | #[derive(Unaligned)]
+71 | #[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>
+             bool
+             i8
+             u8
+             Unaligned1
+             Unaligned2
+             Unaligned3
+             U16<O>
+             U32<O>
            and $N others
    = help: see issue #48214
    = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
diff --git a/tests/ui-nightly/mid_compile_pass.rs b/tests/ui-nightly/mid_compile_pass.rs
new file mode 100644
index 0000000..e0c4bc5
--- /dev/null
+++ b/tests/ui-nightly/mid_compile_pass.rs
@@ -0,0 +1,61 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::KnownLayout;
+
+fn main() {}
+
+// These tests cause errors which are generated by a later compilation pass than
+// the other errors we generate, and so if they're compiled in the same file,
+// the compiler will never get to that pass, and so we won't get the errors.
+
+//
+// KnownLayout errors
+//
+
+fn assert_kl<T: ?Sized + KnownLayout>(_: &T) {}
+
+// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+// |          N |        Y |              N |        N |      KL04 |
+#[derive(KnownLayout)]
+struct KL04<T: ?Sized>(u8, T);
+
+fn test_kl04<T: ?Sized>(kl: &KL04<T>) {
+    assert_kl(kl);
+}
+
+// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+// |          N |        Y |              Y |        N |      KL06 |
+#[derive(KnownLayout)]
+struct KL06<T: ?Sized + KnownLayout>(u8, T);
+
+fn test_kl06<T: ?Sized + KnownLayout>(kl: &KL06<T>) {
+    assert_kl(kl);
+}
+
+// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+// |          Y |        Y |              N |        N |      KL12 |
+#[derive(KnownLayout)]
+#[repr(C)]
+struct KL12<T: ?Sized>(u8, T);
+
+fn test_kl12<T: ?Sized>(kl: &KL12<T>) {
+    assert_kl(kl)
+}
+
+// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+// |          Y |        Y |              N |        Y |      KL13 |
+#[derive(KnownLayout)]
+#[repr(C)]
+struct KL13<T>(u8, T);
+
+fn test_kl13<T>(t: T) -> impl KnownLayout {
+    KL13(0u8, t)
+}
diff --git a/tests/ui-nightly/mid_compile_pass.stderr b/tests/ui-nightly/mid_compile_pass.stderr
new file mode 100644
index 0000000..7fd758c
--- /dev/null
+++ b/tests/ui-nightly/mid_compile_pass.stderr
@@ -0,0 +1,104 @@
+error[E0277]: the trait bound `T: KnownLayout` is not satisfied
+  --> tests/ui-nightly/mid_compile_pass.rs:59:26
+   |
+59 | fn test_kl13<T>(t: T) -> impl KnownLayout {
+   |                          ^^^^^^^^^^^^^^^^ the trait `KnownLayout` is not implemented for `T`
+   |
+note: required for `KL13<T>` to implement `KnownLayout`
+  --> tests/ui-nightly/mid_compile_pass.rs:55:10
+   |
+55 | #[derive(KnownLayout)]
+   |          ^^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro
+   = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider restricting type parameter `T`
+   |
+59 | fn test_kl13<T: zerocopy::KnownLayout>(t: T) -> impl KnownLayout {
+   |               +++++++++++++++++++++++
+
+error[E0277]: the size for values of type `T` cannot be known at compilation time
+  --> tests/ui-nightly/mid_compile_pass.rs:31:15
+   |
+30 | fn test_kl04<T: ?Sized>(kl: &KL04<T>) {
+   |              - this type parameter needs to be `Sized`
+31 |     assert_kl(kl);
+   |     --------- ^^ doesn't have a size known at compile-time
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required because it appears within the type `KL04<T>`
+  --> tests/ui-nightly/mid_compile_pass.rs:28:8
+   |
+28 | struct KL04<T: ?Sized>(u8, T);
+   |        ^^^^
+note: required for `KL04<T>` to implement `KnownLayout`
+  --> tests/ui-nightly/mid_compile_pass.rs:27:10
+   |
+27 | #[derive(KnownLayout)]
+   |          ^^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro
+note: required by a bound in `assert_kl`
+  --> tests/ui-nightly/mid_compile_pass.rs:23:26
+   |
+23 | fn assert_kl<T: ?Sized + KnownLayout>(_: &T) {}
+   |                          ^^^^^^^^^^^ required by this bound in `assert_kl`
+   = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+   |
+30 - fn test_kl04<T: ?Sized>(kl: &KL04<T>) {
+30 + fn test_kl04<T>(kl: &KL04<T>) {
+   |
+
+error[E0277]: the size for values of type `T` cannot be known at compilation time
+  --> tests/ui-nightly/mid_compile_pass.rs:40:15
+   |
+39 | fn test_kl06<T: ?Sized + KnownLayout>(kl: &KL06<T>) {
+   |              - this type parameter needs to be `Sized`
+40 |     assert_kl(kl);
+   |     --------- ^^ doesn't have a size known at compile-time
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required because it appears within the type `KL06<T>`
+  --> tests/ui-nightly/mid_compile_pass.rs:37:8
+   |
+37 | struct KL06<T: ?Sized + KnownLayout>(u8, T);
+   |        ^^^^
+note: required for `KL06<T>` to implement `KnownLayout`
+  --> tests/ui-nightly/mid_compile_pass.rs:36:10
+   |
+36 | #[derive(KnownLayout)]
+   |          ^^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro
+note: required by a bound in `assert_kl`
+  --> tests/ui-nightly/mid_compile_pass.rs:23:26
+   |
+23 | fn assert_kl<T: ?Sized + KnownLayout>(_: &T) {}
+   |                          ^^^^^^^^^^^ required by this bound in `assert_kl`
+   = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+   |
+39 - fn test_kl06<T: ?Sized + KnownLayout>(kl: &KL06<T>) {
+39 + fn test_kl06<T: KnownLayout>(kl: &KL06<T>) {
+   |
+
+error[E0277]: the trait bound `T: KnownLayout` is not satisfied
+  --> tests/ui-nightly/mid_compile_pass.rs:50:15
+   |
+50 |     assert_kl(kl)
+   |     --------- ^^ the trait `KnownLayout` is not implemented for `T`
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required for `KL12<T>` to implement `KnownLayout`
+  --> tests/ui-nightly/mid_compile_pass.rs:45:10
+   |
+45 | #[derive(KnownLayout)]
+   |          ^^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro
+note: required by a bound in `assert_kl`
+  --> tests/ui-nightly/mid_compile_pass.rs:23:26
+   |
+23 | fn assert_kl<T: ?Sized + KnownLayout>(_: &T) {}
+   |                          ^^^^^^^^^^^ required by this bound in `assert_kl`
+   = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider further restricting this bound
+   |
+49 | fn test_kl12<T: ?Sized + zerocopy::KnownLayout>(kl: &KL12<T>) {
+   |                        +++++++++++++++++++++++
diff --git a/tests/ui-nightly/struct.rs b/tests/ui-nightly/struct.rs
index 29aa0e8..c76dc7f 100644
--- a/tests/ui-nightly/struct.rs
+++ b/tests/ui-nightly/struct.rs
@@ -1,6 +1,10 @@
-// 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.
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
 
 #[macro_use]
 extern crate zerocopy;
@@ -8,11 +12,43 @@
 #[path = "../util.rs"]
 mod util;
 
+use zerocopy::KnownLayout;
+
 use self::util::AU16;
 
 fn main() {}
 
 //
+// KnownLayout errors
+//
+
+struct NotKnownLayout;
+
+struct NotKnownLayoutDst([u8]);
+
+// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+// |          N |        N |              N |        N |      KL00 |
+#[derive(KnownLayout)]
+struct KL00(u8, NotKnownLayoutDst);
+
+// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+// |          N |        N |              Y |        N |      KL02 |
+#[derive(KnownLayout)]
+struct KL02(u8, [u8]);
+
+// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+// |          Y |        N |              N |        N |      KL08 |
+#[derive(KnownLayout)]
+#[repr(C)]
+struct KL08(u8, NotKnownLayoutDst);
+
+// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+// |          Y |        N |              N |        Y |      KL09 |
+#[derive(KnownLayout)]
+#[repr(C)]
+struct KL09(NotKnownLayout, NotKnownLayout);
+
+//
 // AsBytes errors
 //
 
@@ -27,6 +63,15 @@
     bar: AU16,
 }
 
+#[derive(AsBytes)]
+#[repr(C, packed(2))]
+struct AsBytes3 {
+    foo: u8,
+    // We'd prefer to use AU64 here, but you can't use aligned types in
+    // packed structs.
+    bar: u64,
+}
+
 //
 // Unaligned errors
 //
diff --git a/tests/ui-nightly/struct.stderr b/tests/ui-nightly/struct.stderr
index a75d070..c3abcbd 100644
--- a/tests/ui-nightly/struct.stderr
+++ b/tests/ui-nightly/struct.stderr
@@ -1,54 +1,143 @@
 error: unsupported on generic structs that are not repr(transparent) or repr(packed)
-  --> tests/ui-nightly/struct.rs:19:10
+  --> tests/ui-nightly/struct.rs:55:10
    |
-19 | #[derive(AsBytes)]
+55 | #[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
+  --> tests/ui-nightly/struct.rs:80:11
    |
-35 | #[repr(C, align(2))]
+80 | #[repr(C, align(2))]
    |           ^^^^^^^^
 
 error: cannot derive Unaligned with repr(align(N > 1))
-  --> tests/ui-nightly/struct.rs:39:21
+  --> tests/ui-nightly/struct.rs:84:21
    |
-39 | #[repr(transparent, align(2))]
+84 | #[repr(transparent, align(2))]
    |                     ^^^^^^^^
 
 error: cannot derive Unaligned with repr(align(N > 1))
-  --> tests/ui-nightly/struct.rs:45:16
+  --> tests/ui-nightly/struct.rs:90:16
    |
-45 | #[repr(packed, align(2))]
+90 | #[repr(packed, align(2))]
    |                ^^^^^^^^
 
 error: cannot derive Unaligned with repr(align(N > 1))
-  --> tests/ui-nightly/struct.rs:49:18
+  --> tests/ui-nightly/struct.rs:94:18
    |
-49 | #[repr(align(1), align(2))]
+94 | #[repr(align(1), align(2))]
    |                  ^^^^^^^^
 
 error: cannot derive Unaligned with repr(align(N > 1))
-  --> tests/ui-nightly/struct.rs:53:8
+  --> tests/ui-nightly/struct.rs:98:8
    |
-53 | #[repr(align(2), align(4))]
+98 | #[repr(align(2), align(4))]
    |        ^^^^^^^^
 
 error[E0692]: transparent struct cannot have other repr hints
-  --> tests/ui-nightly/struct.rs:39:8
+  --> tests/ui-nightly/struct.rs:84:8
    |
-39 | #[repr(transparent, align(2))]
+84 | #[repr(transparent, align(2))]
    |        ^^^^^^^^^^^  ^^^^^^^^
 
-error[E0277]: the trait bound `HasPadding<AsBytes2, true>: ShouldBe<false>` is not satisfied
-  --> tests/ui-nightly/struct.rs:23:10
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> tests/ui-nightly/struct.rs:31:10
    |
-23 | #[derive(AsBytes)]
+31 | #[derive(KnownLayout)]
+   |          ^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: within `KL00`, the trait `Sized` is not implemented for `[u8]`
+note: required because it appears within the type `KL00`
+  --> tests/ui-nightly/struct.rs:32:8
+   |
+32 | struct KL00(u8, NotKnownLayoutDst);
+   |        ^^^^
+   = help: see issue #48214
+   = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
+   = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> tests/ui-nightly/struct.rs:36:10
+   |
+36 | #[derive(KnownLayout)]
+   |          ^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: within `KL02`, the trait `Sized` is not implemented for `[u8]`
+note: required because it appears within the type `KL02`
+  --> tests/ui-nightly/struct.rs:37:8
+   |
+37 | struct KL02(u8, [u8]);
+   |        ^^^^
+   = help: see issue #48214
+   = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
+   = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `NotKnownLayoutDst: KnownLayout` is not satisfied
+  --> tests/ui-nightly/struct.rs:41:10
+   |
+41 | #[derive(KnownLayout)]
+   |          ^^^^^^^^^^^ the trait `KnownLayout` is not implemented for `NotKnownLayoutDst`
+   |
+   = help: the following other types implement trait `KnownLayout`:
+             bool
+             char
+             isize
+             i8
+             i16
+             i32
+             i64
+             i128
+           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 `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `NotKnownLayout: KnownLayout` is not satisfied
+  --> tests/ui-nightly/struct.rs:47:10
+   |
+47 | #[derive(KnownLayout)]
+   |          ^^^^^^^^^^^ the trait `KnownLayout` is not implemented for `NotKnownLayout`
+   |
+   = help: the following other types implement trait `KnownLayout`:
+             bool
+             char
+             isize
+             i8
+             i16
+             i32
+             i64
+             i128
+           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 `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `HasPadding<AsBytes2, true>: ShouldBe<false>` is not satisfied
+  --> tests/ui-nightly/struct.rs:59:10
+   |
+59 | #[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: the trait `ShouldBe<true>` is implemented for `HasPadding<AsBytes2, true>`
    = 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 `HasPadding<AsBytes3, true>: ShouldBe<false>` is not satisfied
+  --> tests/ui-nightly/struct.rs:66:10
+   |
+66 | #[derive(AsBytes)]
+   |          ^^^^^^^ the trait `ShouldBe<false>` is not implemented for `HasPadding<AsBytes3, true>`
+   |
+   = help: the trait `ShouldBe<true>` is implemented for `HasPadding<AsBytes3, true>`
+   = 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[E0587]: type has conflicting packed and align representation hints
+  --> tests/ui-nightly/struct.rs:91:1
+   |
+91 | struct Unaligned3;
+   | ^^^^^^^^^^^^^^^^^
diff --git a/tests/ui-nightly/union.rs b/tests/ui-nightly/union.rs
index e7761e0..8938e78 100644
--- a/tests/ui-nightly/union.rs
+++ b/tests/ui-nightly/union.rs
@@ -1,6 +1,10 @@
-// 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.
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
 
 #[macro_use]
 extern crate zerocopy;
diff --git a/tests/ui-nightly/union.stderr b/tests/ui-nightly/union.stderr
index 9c1f8dd..afc4e8c 100644
--- a/tests/ui-nightly/union.stderr
+++ b/tests/ui-nightly/union.stderr
@@ -1,42 +1,48 @@
 error: unsupported on types with type parameters
-  --> tests/ui-nightly/union.rs:20:10
+  --> tests/ui-nightly/union.rs:24:10
    |
-20 | #[derive(AsBytes)]
+24 | #[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
+  --> tests/ui-nightly/union.rs:42:11
    |
-38 | #[repr(C, align(2))]
+42 | #[repr(C, align(2))]
    |           ^^^^^^^^
 
 error: cannot derive Unaligned with repr(align(N > 1))
-  --> tests/ui-nightly/union.rs:54:16
+  --> tests/ui-nightly/union.rs:58:16
    |
-54 | #[repr(packed, align(2))]
+58 | #[repr(packed, align(2))]
    |                ^^^^^^^^
 
 error: cannot derive Unaligned with repr(align(N > 1))
-  --> tests/ui-nightly/union.rs:60:18
+  --> tests/ui-nightly/union.rs:64:18
    |
-60 | #[repr(align(1), align(2))]
+64 | #[repr(align(1), align(2))]
    |                  ^^^^^^^^
 
 error: cannot derive Unaligned with repr(align(N > 1))
-  --> tests/ui-nightly/union.rs:66:8
+  --> tests/ui-nightly/union.rs:70:8
    |
-66 | #[repr(align(2), align(4))]
+70 | #[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
+  --> tests/ui-nightly/union.rs:30:10
    |
-26 | #[derive(AsBytes)]
+30 | #[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: the trait `ShouldBe<true>` is implemented for `HasPadding<AsBytes2, true>`
    = 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[E0587]: type has conflicting packed and align representation hints
+  --> tests/ui-nightly/union.rs:59:1
+   |
+59 | union Unaligned3 {
+   | ^^^^^^^^^^^^^^^^
diff --git a/tests/ui-stable/derive_transparent.rs b/tests/ui-stable/derive_transparent.rs
index a99f92c..2084d92 100644
--- a/tests/ui-stable/derive_transparent.rs
+++ b/tests/ui-stable/derive_transparent.rs
@@ -1,6 +1,10 @@
-// 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.
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
 
 extern crate zerocopy;
 
diff --git a/tests/ui-stable/derive_transparent.stderr b/tests/ui-stable/derive_transparent.stderr
index 3810def..f24dd48 100644
--- a/tests/ui-stable/derive_transparent.stderr
+++ b/tests/ui-stable/derive_transparent.stderr
@@ -1,111 +1,111 @@
 error[E0277]: the trait bound `NotZerocopy: FromZeroes` is not satisfied
-  --> tests/ui-stable/derive_transparent.rs:33:18
+  --> tests/ui-stable/derive_transparent.rs:37:18
    |
-33 | assert_impl_all!(TransparentStruct<NotZerocopy>: FromZeroes);
+37 | 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>
+             bool
+             char
+             isize
+             i8
+             i16
+             i32
+             i64
+             i128
            and $N others
 note: required for `TransparentStruct<NotZerocopy>` to implement `FromZeroes`
-  --> tests/ui-stable/derive_transparent.rs:23:19
+  --> tests/ui-stable/derive_transparent.rs:27:19
    |
-23 | #[derive(AsBytes, FromZeroes, FromBytes, Unaligned)]
+27 | #[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
+  --> tests/ui-stable/derive_transparent.rs:37:1
    |
-33 | assert_impl_all!(TransparentStruct<NotZerocopy>: FromZeroes);
+37 | 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
+  --> tests/ui-stable/derive_transparent.rs:38:18
    |
-34 | assert_impl_all!(TransparentStruct<NotZerocopy>: FromBytes);
+38 | 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>
+             isize
+             i8
+             i16
+             i32
+             i64
+             i128
+             usize
+             u8
            and $N others
 note: required for `TransparentStruct<NotZerocopy>` to implement `FromBytes`
-  --> tests/ui-stable/derive_transparent.rs:23:31
+  --> tests/ui-stable/derive_transparent.rs:27:31
    |
-23 | #[derive(AsBytes, FromZeroes, FromBytes, Unaligned)]
+27 | #[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
+  --> tests/ui-stable/derive_transparent.rs:38:1
    |
-34 | assert_impl_all!(TransparentStruct<NotZerocopy>: FromBytes);
+38 | 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
+  --> tests/ui-stable/derive_transparent.rs:39:18
    |
-35 | assert_impl_all!(TransparentStruct<NotZerocopy>: AsBytes);
+39 | 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>
+             bool
+             char
+             isize
+             i8
+             i16
+             i32
+             i64
+             i128
            and $N others
 note: required for `TransparentStruct<NotZerocopy>` to implement `AsBytes`
-  --> tests/ui-stable/derive_transparent.rs:23:10
+  --> tests/ui-stable/derive_transparent.rs:27:10
    |
-23 | #[derive(AsBytes, FromZeroes, FromBytes, Unaligned)]
+27 | #[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
+  --> tests/ui-stable/derive_transparent.rs:39:1
    |
-35 | assert_impl_all!(TransparentStruct<NotZerocopy>: AsBytes);
+39 | 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
+  --> tests/ui-stable/derive_transparent.rs:40:18
    |
-36 | assert_impl_all!(TransparentStruct<NotZerocopy>: Unaligned);
+40 | 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>
+             bool
+             i8
+             u8
+             TransparentStruct<T>
+             U16<O>
+             U32<O>
+             U64<O>
+             U128<O>
            and $N others
 note: required for `TransparentStruct<NotZerocopy>` to implement `Unaligned`
-  --> tests/ui-stable/derive_transparent.rs:23:42
+  --> tests/ui-stable/derive_transparent.rs:27:42
    |
-23 | #[derive(AsBytes, FromZeroes, FromBytes, Unaligned)]
+27 | #[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
+  --> tests/ui-stable/derive_transparent.rs:40:1
    |
-36 | assert_impl_all!(TransparentStruct<NotZerocopy>: Unaligned);
+40 | 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 c3d1e27..31d5679 100644
--- a/tests/ui-stable/enum.rs
+++ b/tests/ui-stable/enum.rs
@@ -1,6 +1,10 @@
-// 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.
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
 
 #[macro_use]
 extern crate zerocopy;
diff --git a/tests/ui-stable/enum.stderr b/tests/ui-stable/enum.stderr
index 1e35fa6..a47ce9c 100644
--- a/tests/ui-stable/enum.stderr
+++ b/tests/ui-stable/enum.stderr
@@ -1,199 +1,199 @@
 error: unrecognized representation hint
-  --> tests/ui-stable/enum.rs:15:8
+  --> tests/ui-stable/enum.rs:19:8
    |
-15 | #[repr("foo")]
+19 | #[repr("foo")]
    |        ^^^^^
 
 error: unrecognized representation hint
-  --> tests/ui-stable/enum.rs:21:8
+  --> tests/ui-stable/enum.rs:25:8
    |
-21 | #[repr(foo)]
+25 | #[repr(foo)]
    |        ^^^
 
 error: unsupported representation for deriving FromBytes, AsBytes, or Unaligned on an enum
-  --> tests/ui-stable/enum.rs:27:8
+  --> tests/ui-stable/enum.rs:31:8
    |
-27 | #[repr(transparent)]
+31 | #[repr(transparent)]
    |        ^^^^^^^^^^^
 
 error: conflicting representation hints
-  --> tests/ui-stable/enum.rs:33:1
+  --> tests/ui-stable/enum.rs:37:1
    |
-33 | #[repr(u8, u16)]
+37 | #[repr(u8, u16)]
    | ^
 
 error: must have a non-align #[repr(...)] attribute in order to guarantee this type's memory layout
-  --> tests/ui-stable/enum.rs:38:22
+  --> tests/ui-stable/enum.rs:42:22
    |
-38 | #[derive(FromZeroes, FromBytes)]
+42 | #[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
+  --> tests/ui-stable/enum.rs:52:1
    |
-48 | / enum FromZeroes1 {
-49 | |     A(u8),
-50 | | }
+52 | / enum FromZeroes1 {
+53 | |     A(u8),
+54 | | }
    | |_^
 
 error: only C-like enums can implement FromZeroes
-  --> tests/ui-stable/enum.rs:53:1
+  --> tests/ui-stable/enum.rs:57:1
    |
-53 | / enum FromZeroes2 {
-54 | |     A,
-55 | |     B(u8),
-56 | | }
+57 | / enum FromZeroes2 {
+58 | |     A,
+59 | |     B(u8),
+60 | | }
    | |_^
 
 error: FromZeroes only supported on enums with a variant that has a discriminant of `0`
-  --> tests/ui-stable/enum.rs:59:1
+  --> tests/ui-stable/enum.rs:63:1
    |
-59 | / enum FromZeroes3 {
-60 | |     A = 1,
-61 | |     B,
-62 | | }
+63 | / enum FromZeroes3 {
+64 | |     A = 1,
+65 | |     B,
+66 | | }
    | |_^
 
 error: FromBytes requires repr of "u8", "u16", "i8", or "i16"
-  --> tests/ui-stable/enum.rs:69:8
+  --> tests/ui-stable/enum.rs:73:8
    |
-69 | #[repr(C)]
+73 | #[repr(C)]
    |        ^
 
 error: FromBytes requires repr of "u8", "u16", "i8", or "i16"
-  --> tests/ui-stable/enum.rs:75:8
+  --> tests/ui-stable/enum.rs:79:8
    |
-75 | #[repr(usize)]
+79 | #[repr(usize)]
    |        ^^^^^
 
 error: FromBytes requires repr of "u8", "u16", "i8", or "i16"
-  --> tests/ui-stable/enum.rs:81:8
+  --> tests/ui-stable/enum.rs:85:8
    |
-81 | #[repr(isize)]
+85 | #[repr(isize)]
    |        ^^^^^
 
 error: FromBytes requires repr of "u8", "u16", "i8", or "i16"
-  --> tests/ui-stable/enum.rs:87:8
+  --> tests/ui-stable/enum.rs:91:8
    |
-87 | #[repr(u32)]
+91 | #[repr(u32)]
    |        ^^^
 
 error: FromBytes requires repr of "u8", "u16", "i8", or "i16"
-  --> tests/ui-stable/enum.rs:93:8
+  --> tests/ui-stable/enum.rs:97:8
    |
-93 | #[repr(i32)]
+97 | #[repr(i32)]
    |        ^^^
 
 error: FromBytes requires repr of "u8", "u16", "i8", or "i16"
-  --> tests/ui-stable/enum.rs:99:8
-   |
-99 | #[repr(u64)]
-   |        ^^^
-
-error: FromBytes requires repr of "u8", "u16", "i8", or "i16"
-   --> tests/ui-stable/enum.rs:105:8
+   --> tests/ui-stable/enum.rs:103:8
     |
-105 | #[repr(i64)]
+103 | #[repr(u64)]
+    |        ^^^
+
+error: FromBytes requires repr of "u8", "u16", "i8", or "i16"
+   --> tests/ui-stable/enum.rs:109:8
+    |
+109 | #[repr(i64)]
     |        ^^^
 
 error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
-   --> tests/ui-stable/enum.rs:115:8
+   --> tests/ui-stable/enum.rs:119:8
     |
-115 | #[repr(C)]
+119 | #[repr(C)]
     |        ^
 
 error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
-   --> tests/ui-stable/enum.rs:121:8
+   --> tests/ui-stable/enum.rs:125:8
     |
-121 | #[repr(u16)]
+125 | #[repr(u16)]
     |        ^^^
 
 error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
-   --> tests/ui-stable/enum.rs:127:8
+   --> tests/ui-stable/enum.rs:131:8
     |
-127 | #[repr(i16)]
+131 | #[repr(i16)]
     |        ^^^
 
 error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
-   --> tests/ui-stable/enum.rs:133:8
+   --> tests/ui-stable/enum.rs:137:8
     |
-133 | #[repr(u32)]
+137 | #[repr(u32)]
     |        ^^^
 
 error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
-   --> tests/ui-stable/enum.rs:139:8
+   --> tests/ui-stable/enum.rs:143:8
     |
-139 | #[repr(i32)]
+143 | #[repr(i32)]
     |        ^^^
 
 error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
-   --> tests/ui-stable/enum.rs:145:8
+   --> tests/ui-stable/enum.rs:149:8
     |
-145 | #[repr(u64)]
+149 | #[repr(u64)]
     |        ^^^
 
 error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
-   --> tests/ui-stable/enum.rs:151:8
+   --> tests/ui-stable/enum.rs:155:8
     |
-151 | #[repr(i64)]
+155 | #[repr(i64)]
     |        ^^^
 
 error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
-   --> tests/ui-stable/enum.rs:157:8
+   --> tests/ui-stable/enum.rs:161:8
     |
-157 | #[repr(usize)]
+161 | #[repr(usize)]
     |        ^^^^^
 
 error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
-   --> tests/ui-stable/enum.rs:163:8
+   --> tests/ui-stable/enum.rs:167:8
     |
-163 | #[repr(isize)]
+167 | #[repr(isize)]
     |        ^^^^^
 
 error: cannot derive Unaligned with repr(align(N > 1))
-   --> tests/ui-stable/enum.rs:169:12
+   --> tests/ui-stable/enum.rs:173:12
     |
-169 | #[repr(u8, align(2))]
+173 | #[repr(u8, align(2))]
     |            ^^^^^^^^
 
 error: cannot derive Unaligned with repr(align(N > 1))
-   --> tests/ui-stable/enum.rs:175:12
+   --> tests/ui-stable/enum.rs:179:12
     |
-175 | #[repr(i8, align(2))]
+179 | #[repr(i8, align(2))]
     |            ^^^^^^^^
 
 error: cannot derive Unaligned with repr(align(N > 1))
-   --> tests/ui-stable/enum.rs:181:18
+   --> tests/ui-stable/enum.rs:185:18
     |
-181 | #[repr(align(1), align(2))]
+185 | #[repr(align(1), align(2))]
     |                  ^^^^^^^^
 
 error: cannot derive Unaligned with repr(align(N > 1))
-   --> tests/ui-stable/enum.rs:187:8
+   --> tests/ui-stable/enum.rs:191:8
     |
-187 | #[repr(align(2), align(4))]
+191 | #[repr(align(2), align(4))]
     |        ^^^^^^^^
 
 error[E0565]: meta item in `repr` must be an identifier
-  --> tests/ui-stable/enum.rs:15:8
+  --> tests/ui-stable/enum.rs:19:8
    |
-15 | #[repr("foo")]
+19 | #[repr("foo")]
    |        ^^^^^
 
 error[E0552]: unrecognized representation hint
-  --> tests/ui-stable/enum.rs:21:8
+  --> tests/ui-stable/enum.rs:25:8
    |
-21 | #[repr(foo)]
+25 | #[repr(foo)]
    |        ^^^
    |
-   = help: valid reprs are `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize`
+   = help: valid reprs are `Rust` (default), `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
+  --> tests/ui-stable/enum.rs:37:8
    |
-33 | #[repr(u8, u16)]
+37 | #[repr(u8, u16)]
    |        ^^  ^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
diff --git a/tests/ui-stable/enum_from_bytes_u8_too_few.rs b/tests/ui-stable/enum_from_bytes_u8_too_few.rs
index 4f54ec7..1b1bed3 100644
--- a/tests/ui-stable/enum_from_bytes_u8_too_few.rs
+++ b/tests/ui-stable/enum_from_bytes_u8_too_few.rs
@@ -1,6 +1,10 @@
-// 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.
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
 
 #[macro_use]
 extern crate zerocopy;
diff --git a/tests/ui-stable/enum_from_bytes_u8_too_few.stderr b/tests/ui-stable/enum_from_bytes_u8_too_few.stderr
index 5b60423..5edbabc 100644
--- a/tests/ui-stable/enum_from_bytes_u8_too_few.stderr
+++ b/tests/ui-stable/enum_from_bytes_u8_too_few.stderr
@@ -1,11 +1,11 @@
 error: FromBytes only supported on repr(u8) enum with 256 variants
-   --> tests/ui-stable/enum_from_bytes_u8_too_few.rs:11:1
+   --> tests/ui-stable/enum_from_bytes_u8_too_few.rs:15:1
     |
-11  | / #[repr(u8)]
-12  | | enum Foo {
-13  | |     Variant0,
-14  | |     Variant1,
+15  | / #[repr(u8)]
+16  | | enum Foo {
+17  | |     Variant0,
+18  | |     Variant1,
 ...   |
-267 | |     Variant254,
-268 | | }
+271 | |     Variant254,
+272 | | }
     | |_^
diff --git a/tests/ui-stable/late_compile_pass.rs b/tests/ui-stable/late_compile_pass.rs
index 1b4c603..cd65a6e 100644
--- a/tests/ui-stable/late_compile_pass.rs
+++ b/tests/ui-stable/late_compile_pass.rs
@@ -1,6 +1,10 @@
-// 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.
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
 
 #[macro_use]
 extern crate zerocopy;
@@ -9,6 +13,7 @@
 mod util;
 
 use self::util::{NotZerocopy, AU16};
+use zerocopy::KnownLayout;
 
 fn main() {}
 
diff --git a/tests/ui-stable/late_compile_pass.stderr b/tests/ui-stable/late_compile_pass.stderr
index eab9b97..808054a 100644
--- a/tests/ui-stable/late_compile_pass.stderr
+++ b/tests/ui-stable/late_compile_pass.stderr
@@ -1,56 +1,64 @@
-error[E0277]: the trait bound `NotZerocopy: FromZeroes` is not satisfied
-  --> tests/ui-stable/late_compile_pass.rs:23:10
+warning: unused import: `zerocopy::KnownLayout`
+  --> tests/ui-stable/late_compile_pass.rs:16:5
    |
-23 | #[derive(FromZeroes)]
+16 | use zerocopy::KnownLayout;
+   |     ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(unused_imports)]` on by default
+
+error[E0277]: the trait bound `NotZerocopy: FromZeroes` is not satisfied
+  --> tests/ui-stable/late_compile_pass.rs:28:10
+   |
+28 | #[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>
+             bool
+             char
+             isize
+             i8
+             i16
+             i32
+             i64
+             i128
            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 `NotZerocopy: FromBytes` is not satisfied
-  --> tests/ui-stable/late_compile_pass.rs:32:10
+  --> tests/ui-stable/late_compile_pass.rs:37:10
    |
-32 | #[derive(FromBytes)]
+37 | #[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>
+             isize
+             i8
+             i16
+             i32
+             i64
+             i128
+             usize
+             u8
            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
+  --> tests/ui-stable/late_compile_pass.rs:37:10
    |
-32 | #[derive(FromBytes)]
+37 | #[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>
+             bool
+             char
+             isize
+             i8
+             i16
+             i32
+             i64
+             i128
            and $N others
 note: required by a bound in `FromBytes`
   --> $WORKSPACE/src/lib.rs
@@ -60,77 +68,77 @@
    = 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-stable/late_compile_pass.rs:41:10
+  --> tests/ui-stable/late_compile_pass.rs:46:10
    |
-41 | #[derive(AsBytes)]
+46 | #[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>
+             bool
+             char
+             isize
+             i8
+             i16
+             i32
+             i64
+             i128
            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
+  --> tests/ui-stable/late_compile_pass.rs:56:10
    |
-51 | #[derive(Unaligned)]
+56 | #[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>
+             bool
+             i8
+             u8
+             Unaligned1
+             Unaligned2
+             Unaligned3
+             U16<O>
+             U32<O>
            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 `AU16: Unaligned` is not satisfied
-  --> tests/ui-stable/late_compile_pass.rs:59:10
+  --> tests/ui-stable/late_compile_pass.rs:64:10
    |
-59 | #[derive(Unaligned)]
+64 | #[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>
+             bool
+             i8
+             u8
+             Unaligned1
+             Unaligned2
+             Unaligned3
+             U16<O>
+             U32<O>
            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 `AU16: Unaligned` is not satisfied
-  --> tests/ui-stable/late_compile_pass.rs:66:10
+  --> tests/ui-stable/late_compile_pass.rs:71:10
    |
-66 | #[derive(Unaligned)]
+71 | #[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>
+             bool
+             i8
+             u8
+             Unaligned1
+             Unaligned2
+             Unaligned3
+             U16<O>
+             U32<O>
            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/mid_compile_pass.rs b/tests/ui-stable/mid_compile_pass.rs
new file mode 100644
index 0000000..e0c4bc5
--- /dev/null
+++ b/tests/ui-stable/mid_compile_pass.rs
@@ -0,0 +1,61 @@
+// Copyright 2023 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
+
+extern crate zerocopy;
+
+use zerocopy::KnownLayout;
+
+fn main() {}
+
+// These tests cause errors which are generated by a later compilation pass than
+// the other errors we generate, and so if they're compiled in the same file,
+// the compiler will never get to that pass, and so we won't get the errors.
+
+//
+// KnownLayout errors
+//
+
+fn assert_kl<T: ?Sized + KnownLayout>(_: &T) {}
+
+// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+// |          N |        Y |              N |        N |      KL04 |
+#[derive(KnownLayout)]
+struct KL04<T: ?Sized>(u8, T);
+
+fn test_kl04<T: ?Sized>(kl: &KL04<T>) {
+    assert_kl(kl);
+}
+
+// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+// |          N |        Y |              Y |        N |      KL06 |
+#[derive(KnownLayout)]
+struct KL06<T: ?Sized + KnownLayout>(u8, T);
+
+fn test_kl06<T: ?Sized + KnownLayout>(kl: &KL06<T>) {
+    assert_kl(kl);
+}
+
+// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+// |          Y |        Y |              N |        N |      KL12 |
+#[derive(KnownLayout)]
+#[repr(C)]
+struct KL12<T: ?Sized>(u8, T);
+
+fn test_kl12<T: ?Sized>(kl: &KL12<T>) {
+    assert_kl(kl)
+}
+
+// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+// |          Y |        Y |              N |        Y |      KL13 |
+#[derive(KnownLayout)]
+#[repr(C)]
+struct KL13<T>(u8, T);
+
+fn test_kl13<T>(t: T) -> impl KnownLayout {
+    KL13(0u8, t)
+}
diff --git a/tests/ui-stable/mid_compile_pass.stderr b/tests/ui-stable/mid_compile_pass.stderr
new file mode 100644
index 0000000..f39bcdb
--- /dev/null
+++ b/tests/ui-stable/mid_compile_pass.stderr
@@ -0,0 +1,104 @@
+error[E0277]: the trait bound `T: KnownLayout` is not satisfied
+  --> tests/ui-stable/mid_compile_pass.rs:59:26
+   |
+59 | fn test_kl13<T>(t: T) -> impl KnownLayout {
+   |                          ^^^^^^^^^^^^^^^^ the trait `KnownLayout` is not implemented for `T`
+   |
+note: required for `KL13<T>` to implement `KnownLayout`
+  --> tests/ui-stable/mid_compile_pass.rs:55:10
+   |
+55 | #[derive(KnownLayout)]
+   |          ^^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro
+   = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider restricting type parameter `T`
+   |
+59 | fn test_kl13<T: zerocopy::KnownLayout>(t: T) -> impl KnownLayout {
+   |               +++++++++++++++++++++++
+
+error[E0277]: the size for values of type `T` cannot be known at compilation time
+  --> tests/ui-stable/mid_compile_pass.rs:31:15
+   |
+30 | fn test_kl04<T: ?Sized>(kl: &KL04<T>) {
+   |              - this type parameter needs to be `Sized`
+31 |     assert_kl(kl);
+   |     --------- ^^ doesn't have a size known at compile-time
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required because it appears within the type `KL04<T>`
+  --> tests/ui-stable/mid_compile_pass.rs:28:8
+   |
+28 | struct KL04<T: ?Sized>(u8, T);
+   |        ^^^^
+note: required for `KL04<T>` to implement `KnownLayout`
+  --> tests/ui-stable/mid_compile_pass.rs:27:10
+   |
+27 | #[derive(KnownLayout)]
+   |          ^^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro
+note: required by a bound in `assert_kl`
+  --> tests/ui-stable/mid_compile_pass.rs:23:26
+   |
+23 | fn assert_kl<T: ?Sized + KnownLayout>(_: &T) {}
+   |                          ^^^^^^^^^^^ required by this bound in `assert_kl`
+   = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+   |
+30 - fn test_kl04<T: ?Sized>(kl: &KL04<T>) {
+30 + fn test_kl04<T>(kl: &KL04<T>) {
+   |
+
+error[E0277]: the size for values of type `T` cannot be known at compilation time
+  --> tests/ui-stable/mid_compile_pass.rs:40:15
+   |
+39 | fn test_kl06<T: ?Sized + KnownLayout>(kl: &KL06<T>) {
+   |              - this type parameter needs to be `Sized`
+40 |     assert_kl(kl);
+   |     --------- ^^ doesn't have a size known at compile-time
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required because it appears within the type `KL06<T>`
+  --> tests/ui-stable/mid_compile_pass.rs:37:8
+   |
+37 | struct KL06<T: ?Sized + KnownLayout>(u8, T);
+   |        ^^^^
+note: required for `KL06<T>` to implement `KnownLayout`
+  --> tests/ui-stable/mid_compile_pass.rs:36:10
+   |
+36 | #[derive(KnownLayout)]
+   |          ^^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro
+note: required by a bound in `assert_kl`
+  --> tests/ui-stable/mid_compile_pass.rs:23:26
+   |
+23 | fn assert_kl<T: ?Sized + KnownLayout>(_: &T) {}
+   |                          ^^^^^^^^^^^ required by this bound in `assert_kl`
+   = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+   |
+39 - fn test_kl06<T: ?Sized + KnownLayout>(kl: &KL06<T>) {
+39 + fn test_kl06<T: KnownLayout>(kl: &KL06<T>) {
+   |
+
+error[E0277]: the trait bound `T: KnownLayout` is not satisfied
+  --> tests/ui-stable/mid_compile_pass.rs:50:15
+   |
+50 |     assert_kl(kl)
+   |     --------- ^^ the trait `KnownLayout` is not implemented for `T`
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required for `KL12<T>` to implement `KnownLayout`
+  --> tests/ui-stable/mid_compile_pass.rs:45:10
+   |
+45 | #[derive(KnownLayout)]
+   |          ^^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro
+note: required by a bound in `assert_kl`
+  --> tests/ui-stable/mid_compile_pass.rs:23:26
+   |
+23 | fn assert_kl<T: ?Sized + KnownLayout>(_: &T) {}
+   |                          ^^^^^^^^^^^ required by this bound in `assert_kl`
+   = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider further restricting this bound
+   |
+49 | fn test_kl12<T: ?Sized + zerocopy::KnownLayout>(kl: &KL12<T>) {
+   |                        +++++++++++++++++++++++
diff --git a/tests/ui-stable/struct.rs b/tests/ui-stable/struct.rs
index 29aa0e8..c76dc7f 100644
--- a/tests/ui-stable/struct.rs
+++ b/tests/ui-stable/struct.rs
@@ -1,6 +1,10 @@
-// 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.
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
 
 #[macro_use]
 extern crate zerocopy;
@@ -8,11 +12,43 @@
 #[path = "../util.rs"]
 mod util;
 
+use zerocopy::KnownLayout;
+
 use self::util::AU16;
 
 fn main() {}
 
 //
+// KnownLayout errors
+//
+
+struct NotKnownLayout;
+
+struct NotKnownLayoutDst([u8]);
+
+// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+// |          N |        N |              N |        N |      KL00 |
+#[derive(KnownLayout)]
+struct KL00(u8, NotKnownLayoutDst);
+
+// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+// |          N |        N |              Y |        N |      KL02 |
+#[derive(KnownLayout)]
+struct KL02(u8, [u8]);
+
+// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+// |          Y |        N |              N |        N |      KL08 |
+#[derive(KnownLayout)]
+#[repr(C)]
+struct KL08(u8, NotKnownLayoutDst);
+
+// | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
+// |          Y |        N |              N |        Y |      KL09 |
+#[derive(KnownLayout)]
+#[repr(C)]
+struct KL09(NotKnownLayout, NotKnownLayout);
+
+//
 // AsBytes errors
 //
 
@@ -27,6 +63,15 @@
     bar: AU16,
 }
 
+#[derive(AsBytes)]
+#[repr(C, packed(2))]
+struct AsBytes3 {
+    foo: u8,
+    // We'd prefer to use AU64 here, but you can't use aligned types in
+    // packed structs.
+    bar: u64,
+}
+
 //
 // Unaligned errors
 //
diff --git a/tests/ui-stable/struct.stderr b/tests/ui-stable/struct.stderr
index a82920e..a93d7c4 100644
--- a/tests/ui-stable/struct.stderr
+++ b/tests/ui-stable/struct.stderr
@@ -1,53 +1,131 @@
 error: unsupported on generic structs that are not repr(transparent) or repr(packed)
-  --> tests/ui-stable/struct.rs:19:10
+  --> tests/ui-stable/struct.rs:55:10
    |
-19 | #[derive(AsBytes)]
+55 | #[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:35:11
+  --> tests/ui-stable/struct.rs:80:11
    |
-35 | #[repr(C, align(2))]
+80 | #[repr(C, align(2))]
    |           ^^^^^^^^
 
 error: cannot derive Unaligned with repr(align(N > 1))
-  --> tests/ui-stable/struct.rs:39:21
+  --> tests/ui-stable/struct.rs:84:21
    |
-39 | #[repr(transparent, align(2))]
+84 | #[repr(transparent, align(2))]
    |                     ^^^^^^^^
 
 error: cannot derive Unaligned with repr(align(N > 1))
-  --> tests/ui-stable/struct.rs:45:16
+  --> tests/ui-stable/struct.rs:90:16
    |
-45 | #[repr(packed, align(2))]
+90 | #[repr(packed, align(2))]
    |                ^^^^^^^^
 
 error: cannot derive Unaligned with repr(align(N > 1))
-  --> tests/ui-stable/struct.rs:49:18
+  --> tests/ui-stable/struct.rs:94:18
    |
-49 | #[repr(align(1), align(2))]
+94 | #[repr(align(1), align(2))]
    |                  ^^^^^^^^
 
 error: cannot derive Unaligned with repr(align(N > 1))
-  --> tests/ui-stable/struct.rs:53:8
+  --> tests/ui-stable/struct.rs:98:8
    |
-53 | #[repr(align(2), align(4))]
+98 | #[repr(align(2), align(4))]
    |        ^^^^^^^^
 
 error[E0692]: transparent struct cannot have other repr hints
-  --> tests/ui-stable/struct.rs:39:8
+  --> tests/ui-stable/struct.rs:84:8
    |
-39 | #[repr(transparent, align(2))]
+84 | #[repr(transparent, align(2))]
    |        ^^^^^^^^^^^  ^^^^^^^^
 
-error[E0277]: the trait bound `HasPadding<AsBytes2, true>: ShouldBe<false>` is not satisfied
-  --> tests/ui-stable/struct.rs:23:10
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> tests/ui-stable/struct.rs:31:10
    |
-23 | #[derive(AsBytes)]
+31 | #[derive(KnownLayout)]
+   |          ^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: within `KL00`, the trait `Sized` is not implemented for `[u8]`
+note: required because it appears within the type `KL00`
+  --> tests/ui-stable/struct.rs:32:8
+   |
+32 | struct KL00(u8, NotKnownLayoutDst);
+   |        ^^^^
+   = help: see issue #48214
+   = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> tests/ui-stable/struct.rs:36:10
+   |
+36 | #[derive(KnownLayout)]
+   |          ^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: within `KL02`, the trait `Sized` is not implemented for `[u8]`
+note: required because it appears within the type `KL02`
+  --> tests/ui-stable/struct.rs:37:8
+   |
+37 | struct KL02(u8, [u8]);
+   |        ^^^^
+   = help: see issue #48214
+   = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `NotKnownLayoutDst: KnownLayout` is not satisfied
+  --> tests/ui-stable/struct.rs:41:10
+   |
+41 | #[derive(KnownLayout)]
+   |          ^^^^^^^^^^^ the trait `KnownLayout` is not implemented for `NotKnownLayoutDst`
+   |
+   = help: the following other types implement trait `KnownLayout`:
+             bool
+             char
+             isize
+             i8
+             i16
+             i32
+             i64
+             i128
+           and $N others
+   = help: see issue #48214
+   = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `NotKnownLayout: KnownLayout` is not satisfied
+  --> tests/ui-stable/struct.rs:47:10
+   |
+47 | #[derive(KnownLayout)]
+   |          ^^^^^^^^^^^ the trait `KnownLayout` is not implemented for `NotKnownLayout`
+   |
+   = help: the following other types implement trait `KnownLayout`:
+             bool
+             char
+             isize
+             i8
+             i16
+             i32
+             i64
+             i128
+           and $N others
+   = help: see issue #48214
+   = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `HasPadding<AsBytes2, true>: ShouldBe<false>` is not satisfied
+  --> tests/ui-stable/struct.rs:59:10
+   |
+59 | #[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)
+
+error[E0277]: the trait bound `HasPadding<AsBytes3, true>: ShouldBe<false>` is not satisfied
+  --> tests/ui-stable/struct.rs:66:10
+   |
+66 | #[derive(AsBytes)]
+   |          ^^^^^^^ the trait `ShouldBe<false>` is not implemented for `HasPadding<AsBytes3, 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 e7761e0..8938e78 100644
--- a/tests/ui-stable/union.rs
+++ b/tests/ui-stable/union.rs
@@ -1,6 +1,10 @@
-// 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.
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
 
 #[macro_use]
 extern crate zerocopy;
diff --git a/tests/ui-stable/union.stderr b/tests/ui-stable/union.stderr
index 6671271..8d5cbbb 100644
--- a/tests/ui-stable/union.stderr
+++ b/tests/ui-stable/union.stderr
@@ -1,39 +1,39 @@
 error: unsupported on types with type parameters
-  --> tests/ui-stable/union.rs:20:10
+  --> tests/ui-stable/union.rs:24:10
    |
-20 | #[derive(AsBytes)]
+24 | #[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:38:11
+  --> tests/ui-stable/union.rs:42:11
    |
-38 | #[repr(C, align(2))]
+42 | #[repr(C, align(2))]
    |           ^^^^^^^^
 
 error: cannot derive Unaligned with repr(align(N > 1))
-  --> tests/ui-stable/union.rs:54:16
+  --> tests/ui-stable/union.rs:58:16
    |
-54 | #[repr(packed, align(2))]
+58 | #[repr(packed, align(2))]
    |                ^^^^^^^^
 
 error: cannot derive Unaligned with repr(align(N > 1))
-  --> tests/ui-stable/union.rs:60:18
+  --> tests/ui-stable/union.rs:64:18
    |
-60 | #[repr(align(1), align(2))]
+64 | #[repr(align(1), align(2))]
    |                  ^^^^^^^^
 
 error: cannot derive Unaligned with repr(align(N > 1))
-  --> tests/ui-stable/union.rs:66:8
+  --> tests/ui-stable/union.rs:70:8
    |
-66 | #[repr(align(2), align(4))]
+70 | #[repr(align(2), align(4))]
    |        ^^^^^^^^
 
 error[E0277]: the trait bound `HasPadding<AsBytes2, true>: ShouldBe<false>` is not satisfied
-  --> tests/ui-stable/union.rs:26:10
+  --> tests/ui-stable/union.rs:30:10
    |
-26 | #[derive(AsBytes)]
+30 | #[derive(AsBytes)]
    |          ^^^^^^^ the trait `ShouldBe<false>` is not implemented for `HasPadding<AsBytes2, true>`
    |
    = help: the trait `ShouldBe<VALUE>` is implemented for `HasPadding<T, VALUE>`
diff --git a/tests/union_as_bytes.rs b/tests/union_as_bytes.rs
index 62b8827..84f5181 100644
--- a/tests/union_as_bytes.rs
+++ b/tests/union_as_bytes.rs
@@ -1,6 +1,10 @@
-// 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.
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
 
 #![allow(warnings)]
 
diff --git a/tests/union_from_bytes.rs b/tests/union_from_bytes.rs
index dae2491..4635735 100644
--- a/tests/union_from_bytes.rs
+++ b/tests/union_from_bytes.rs
@@ -1,6 +1,10 @@
-// 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.
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
 
 #![allow(warnings)]
 
@@ -50,3 +54,19 @@
 }
 
 assert_impl_all!(TypeParams<'static, (), IntoIter<()>>: FromBytes);
+
+// Deriving `FromBytes` should work if the union has bounded parameters.
+
+#[derive(FromZeroes, FromBytes)]
+#[repr(C)]
+union WithParams<'a: 'b, 'b: 'a, const N: usize, T: 'a + 'b + FromBytes>
+where
+    'a: 'b,
+    'b: 'a,
+    T: 'a + 'b + Copy + FromBytes,
+{
+    a: [T; N],
+    b: PhantomData<&'a &'b ()>,
+}
+
+assert_impl_all!(WithParams<'static, 'static, 42, u8>: FromBytes);
diff --git a/tests/union_from_zeroes.rs b/tests/union_from_zeroes.rs
index b5822de..935fc15 100644
--- a/tests/union_from_zeroes.rs
+++ b/tests/union_from_zeroes.rs
@@ -1,6 +1,10 @@
-// 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.
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
 
 #![allow(warnings)]
 
@@ -50,3 +54,19 @@
 }
 
 assert_impl_all!(TypeParams<'static, (), IntoIter<()>>: FromZeroes);
+
+// Deriving `FromZeroes` should work if the union has bounded parameters.
+
+#[derive(FromZeroes)]
+#[repr(C)]
+union WithParams<'a: 'b, 'b: 'a, const N: usize, T: 'a + 'b + FromZeroes>
+where
+    'a: 'b,
+    'b: 'a,
+    T: 'a + 'b + Copy + FromZeroes,
+{
+    a: [T; N],
+    b: PhantomData<&'a &'b ()>,
+}
+
+assert_impl_all!(WithParams<'static, 'static, 42, u8>: FromZeroes);
diff --git a/tests/union_known_layout.rs b/tests/union_known_layout.rs
new file mode 100644
index 0000000..337ab4a
--- /dev/null
+++ b/tests/union_known_layout.rs
@@ -0,0 +1,65 @@
+// 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::KnownLayout};
+
+#[derive(Clone, Copy, KnownLayout)]
+union Zst {
+    a: (),
+}
+
+assert_impl_all!(Zst: KnownLayout);
+
+#[derive(KnownLayout)]
+union One {
+    a: bool,
+}
+
+assert_impl_all!(One: KnownLayout);
+
+#[derive(KnownLayout)]
+union Two {
+    a: bool,
+    b: Zst,
+}
+
+assert_impl_all!(Two: KnownLayout);
+
+#[derive(KnownLayout)]
+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<()>>: KnownLayout);
+
+// Deriving `KnownLayout` should work if the union has bounded parameters.
+
+#[derive(KnownLayout)]
+#[repr(C)]
+union WithParams<'a: 'b, 'b: 'a, const N: usize, T: 'a + 'b + KnownLayout>
+where
+    'a: 'b,
+    'b: 'a,
+    T: 'a + 'b + Copy + KnownLayout,
+{
+    a: [T; N],
+    b: PhantomData<&'a &'b ()>,
+}
+
+assert_impl_all!(WithParams<'static, 'static, 42, u8>: KnownLayout);
diff --git a/tests/union_unaligned.rs b/tests/union_unaligned.rs
index 9ccfe93..5ba3ac7 100644
--- a/tests/union_unaligned.rs
+++ b/tests/union_unaligned.rs
@@ -1,6 +1,10 @@
-// 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.
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
 
 #![allow(warnings)]
 
diff --git a/tests/util.rs b/tests/util.rs
index 7615d84..a8656fb 100644
--- a/tests/util.rs
+++ b/tests/util.rs
@@ -1,16 +1,20 @@
-// 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.
+// Copyright 2019 The Fuchsia Authors
+//
+// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
+// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
+// This file may not be copied, modified, or distributed except according to
+// those terms.
 
-use zerocopy::{AsBytes, FromBytes, FromZeroes};
+use zerocopy::{AsBytes, FromBytes, FromZeroes, KnownLayout};
 
 /// A type that doesn't implement any zerocopy traits.
-pub struct NotZerocopy(());
+pub struct NotZerocopy<T = ()>(T);
 
 /// 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)]
+#[derive(KnownLayout, FromZeroes, FromBytes, AsBytes, Copy, Clone)]
 #[repr(C, align(2))]
 pub struct AU16(u16);