about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-12-04 14:46:49 +0000
committerbors <bors@rust-lang.org>2023-12-04 14:46:49 +0000
commite281163dc83dd747a817bdfbb81bf59c3747f7dc (patch)
treedef4231e0d57fa3428af349f4fb04a61772f3858
parent0a83e43f282353398e4b22466cf1f4e3cc8c1682 (diff)
parentf1397e6ff2b3fa8e6efa4815f603d055c172432d (diff)
downloadrust-e281163dc83dd747a817bdfbb81bf59c3747f7dc.tar.gz
rust-e281163dc83dd747a817bdfbb81bf59c3747f7dc.zip
Auto merge of #118602 - TaKO8Ki:rollup-njcouns, r=TaKO8Ki
Rollup of 5 pull requests

Successful merges:

 - #118495 (Restrict what symbols can be used in `#[diagnostic::on_unimplemented]` format strings)
 - #118540 (codegen, miri: fix computing the offset of an unsized field in a packed struct)
 - #118551 (more targeted errors when extern types end up in places they should not)
 - #118573 (rustc: Harmonize `DefKind` and `DefPathData`)
 - #118586 (Improve example in `slice::windows()` doc)

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_ast_lowering/src/asm.rs4
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs5
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs12
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs21
-rw-r--r--compiler/rustc_codegen_llvm/src/builder.rs9
-rw-r--r--compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/operand.rs1
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/place.rs22
-rw-r--r--compiler/rustc_const_eval/src/interpret/eval_context.rs6
-rw-r--r--compiler/rustc_const_eval/src/interpret/projection.rs12
-rw-r--r--compiler/rustc_hir/src/def.rs37
-rw-r--r--compiler/rustc_hir/src/definitions.rs18
-rw-r--r--compiler/rustc_middle/src/ty/context.rs3
-rw-r--r--compiler/rustc_middle/src/ty/instance.rs2
-rw-r--r--compiler/rustc_middle/src/ty/print/mod.rs2
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs4
-rw-r--r--compiler/rustc_resolve/src/def_collector.rs128
-rw-r--r--compiler/rustc_resolve/src/lib.rs4
-rw-r--r--compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs5
-rw-r--r--compiler/rustc_symbol_mangling/src/v0.rs5
-rw-r--r--compiler/rustc_trait_selection/messages.ftl3
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs147
-rw-r--r--compiler/rustc_ty_utils/src/abi.rs12
-rw-r--r--compiler/rustc_ty_utils/src/assoc.rs7
-rw-r--r--library/core/src/slice/mod.rs10
-rw-r--r--src/tools/miri/tests/pass/issues/issue-3200-packed-field-offset.rs35
-rw-r--r--src/tools/miri/tests/pass/issues/issue-3200-packed2-field-offset.rs38
-rw-r--r--tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.rs67
-rw-r--r--tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.stderr305
-rw-r--r--tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.rs8
-rw-r--r--tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.stderr54
-rw-r--r--tests/ui/packed/issue-118537-field-offset-ice.rs39
-rw-r--r--tests/ui/packed/issue-118537-field-offset.rs36
33 files changed, 854 insertions, 209 deletions
diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs
index b75a686b819..7111daa2ea9 100644
--- a/compiler/rustc_ast_lowering/src/asm.rs
+++ b/compiler/rustc_ast_lowering/src/asm.rs
@@ -14,8 +14,8 @@ use rustc_ast::*;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::definitions::DefPathData;
 use rustc_session::parse::feature_err;
+use rustc_span::symbol::kw;
 use rustc_span::{sym, Span};
 use rustc_target::asm;
 use std::collections::hash_map::Entry;
@@ -227,7 +227,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                             self.create_def(
                                 parent_def_id.def_id,
                                 node_id,
-                                DefPathData::AnonConst,
+                                kw::Empty,
                                 DefKind::AnonConst,
                                 *op_sp,
                             );
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index 5b07299d411..eb1a1d15027 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -13,10 +13,9 @@ use rustc_ast::*;
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::definitions::DefPathData;
 use rustc_session::errors::report_lit_error;
 use rustc_span::source_map::{respan, Spanned};
-use rustc_span::symbol::{sym, Ident, Symbol};
+use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::DUMMY_SP;
 use rustc_span::{DesugaringKind, Span};
 use thin_vec::{thin_vec, ThinVec};
@@ -376,7 +375,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 self.create_def(
                     parent_def_id.def_id,
                     node_id,
-                    DefPathData::AnonConst,
+                    kw::Empty,
                     DefKind::AnonConst,
                     f.span,
                 );
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index fbbb9d7a52a..f0f3e2c3c74 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -3,7 +3,6 @@ use super::ResolverAstLoweringExt;
 use super::{AstOwner, ImplTraitContext, ImplTraitPosition};
 use super::{FnDeclKind, LoweringContext, ParamMode};
 
-use hir::definitions::DefPathData;
 use rustc_ast::ptr::P;
 use rustc_ast::visit::AssocCtxt;
 use rustc_ast::*;
@@ -1367,7 +1366,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 let def_id = self.create_def(
                     self.local_def_id(parent_node_id),
                     param_node_id,
-                    DefPathData::TypeNs(sym::host),
+                    sym::host,
                     DefKind::ConstParam,
                     span,
                 );
@@ -1427,13 +1426,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
         if let Some((span, hir_id, def_id)) = host_param_parts {
             let const_node_id = self.next_node_id();
-            let anon_const = self.create_def(
-                def_id,
-                const_node_id,
-                DefPathData::AnonConst,
-                DefKind::AnonConst,
-                span,
-            );
+            let anon_const =
+                self.create_def(def_id, const_node_id, kw::Empty, DefKind::AnonConst, span);
 
             let const_id = self.next_id();
             let const_expr_id = self.next_id();
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index eb6d11a72e6..aa8ad978451 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -58,7 +58,6 @@ use rustc_errors::{DiagnosticArgFromDisplay, StashKey};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};
 use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
-use rustc_hir::definitions::DefPathData;
 use rustc_hir::{ConstArg, GenericArg, ItemLocalId, ParamName, TraitCandidate};
 use rustc_index::{Idx, IndexSlice, IndexVec};
 use rustc_middle::{
@@ -499,20 +498,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         &mut self,
         parent: LocalDefId,
         node_id: ast::NodeId,
-        data: DefPathData,
+        name: Symbol,
         def_kind: DefKind,
         span: Span,
     ) -> LocalDefId {
         debug_assert_ne!(node_id, ast::DUMMY_NODE_ID);
         assert!(
             self.opt_local_def_id(node_id).is_none(),
-            "adding a def'n for node-id {:?} and data {:?} but a previous def'n exists: {:?}",
+            "adding a def'n for node-id {:?} and def kind {:?} but a previous def'n exists: {:?}",
             node_id,
-            data,
+            def_kind,
             self.tcx.hir().def_key(self.local_def_id(node_id)),
         );
 
-        let def_id = self.tcx.at(span).create_def(parent, data, def_kind).def_id();
+        let def_id = self.tcx.at(span).create_def(parent, name, def_kind).def_id();
 
         debug!("create_def: def_id_to_node_id[{:?}] <-> {:?}", def_id, node_id);
         self.resolver.node_id_to_def_id.insert(node_id, def_id);
@@ -809,7 +808,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 let _def_id = self.create_def(
                     self.current_hir_id_owner.def_id,
                     param,
-                    DefPathData::LifetimeNs(kw::UnderscoreLifetime),
+                    kw::UnderscoreLifetime,
                     DefKind::LifetimeParam,
                     ident.span,
                 );
@@ -1227,7 +1226,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                                 let def_id = self.create_def(
                                     parent_def_id.def_id,
                                     node_id,
-                                    DefPathData::AnonConst,
+                                    kw::Empty,
                                     DefKind::AnonConst,
                                     span,
                                 );
@@ -1465,7 +1464,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                         self.create_def(
                             self.current_hir_id_owner.def_id,
                             *def_node_id,
-                            DefPathData::TypeNs(ident.name),
+                            ident.name,
                             DefKind::TyParam,
                             span,
                         );
@@ -1619,7 +1618,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         let opaque_ty_def_id = self.create_def(
             self.current_hir_id_owner.def_id,
             opaque_ty_node_id,
-            DefPathData::ImplTrait,
+            kw::Empty,
             DefKind::OpaqueTy,
             opaque_ty_span,
         );
@@ -1674,7 +1673,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 let duplicated_lifetime_def_id = self.create_def(
                     opaque_ty_def_id,
                     duplicated_lifetime_node_id,
-                    DefPathData::LifetimeNs(lifetime.ident.name),
+                    lifetime.ident.name,
                     DefKind::LifetimeParam,
                     lifetime.ident.span,
                 );
@@ -2549,7 +2548,7 @@ impl<'hir> GenericArgsCtor<'hir> {
         let def_id = lcx.create_def(
             lcx.current_hir_id_owner.def_id,
             id,
-            DefPathData::AnonConst,
+            kw::Empty,
             DefKind::AnonConst,
             span,
         );
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index 7b259055d40..acd85dd9a2d 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -489,6 +489,15 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
 
     #[instrument(level = "trace", skip(self))]
     fn load_operand(&mut self, place: PlaceRef<'tcx, &'ll Value>) -> OperandRef<'tcx, &'ll Value> {
+        if place.layout.is_unsized() {
+            let tail = self.tcx.struct_tail_with_normalize(place.layout.ty, |ty| ty, || {});
+            if matches!(tail.kind(), ty::Foreign(..)) {
+                // Unsized locals and, at least conceptually, even unsized arguments must be copied
+                // around, which requires dynamically determining their size. Therefore, we cannot
+                // allow `extern` types here. Consult t-opsem before removing this check.
+                panic!("unsized locals must not be `extern` types");
+            }
+        }
         assert_eq!(place.llextra.is_some(), place.layout.is_unsized());
 
         if place.layout.is_zst() {
diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
index 839cc4dabe3..8630e5623e1 100644
--- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
+++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
@@ -594,7 +594,7 @@ fn push_unqualified_item_name(
         DefPathData::CrateRoot => {
             output.push_str(tcx.crate_name(def_id.krate).as_str());
         }
-        DefPathData::ClosureExpr => {
+        DefPathData::Closure => {
             let label = coroutine_kind_label(tcx.coroutine_kind(def_id));
 
             push_disambiguated_special_name(
diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs
index 0ab2b7ecd9c..6661f1f81e6 100644
--- a/compiler/rustc_codegen_ssa/src/mir/operand.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs
@@ -414,6 +414,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue<V> {
                 // value is through `undef`/`poison`, and the store itself is useless.
             }
             OperandValue::Ref(r, None, source_align) => {
+                assert!(dest.layout.is_sized(), "cannot directly store unsized values");
                 if flags.contains(MemFlags::NONTEMPORAL) {
                     // HACK(nox): This is inefficient but there is no nontemporal memcpy.
                     let ty = bx.backend_type(dest.layout);
diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs
index 45795a7f735..83425dee1a8 100644
--- a/compiler/rustc_codegen_ssa/src/mir/place.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/place.rs
@@ -143,7 +143,8 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
         // Simple cases, which don't need DST adjustment:
         //   * no metadata available - just log the case
         //   * known alignment - sized types, `[T]`, `str` or a foreign type
-        //   * packed struct - there is no alignment padding
+        // Note that looking at `field.align` is incorrect since that is not necessarily equal
+        // to the dynamic alignment of the type.
         match field.ty.kind() {
             _ if self.llextra.is_none() => {
                 debug!(
@@ -154,14 +155,6 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
             }
             _ if field.is_sized() => return simple(),
             ty::Slice(..) | ty::Str | ty::Foreign(..) => return simple(),
-            ty::Adt(def, _) => {
-                if def.repr().packed() {
-                    // FIXME(eddyb) generalize the adjustment when we
-                    // start supporting packing to larger alignments.
-                    assert_eq!(self.layout.align.abi.bytes(), 1);
-                    return simple();
-                }
-            }
             _ => {}
         }
 
@@ -186,7 +179,16 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
         let unaligned_offset = bx.cx().const_usize(offset.bytes());
 
         // Get the alignment of the field
-        let (_, unsized_align) = glue::size_and_align_of_dst(bx, field.ty, meta);
+        let (_, mut unsized_align) = glue::size_and_align_of_dst(bx, field.ty, meta);
+
+        // For packed types, we need to cap alignment.
+        if let ty::Adt(def, _) = self.layout.ty.kind()
+            && let Some(packed) = def.repr().pack
+        {
+            let packed = bx.const_usize(packed.bytes());
+            let cmp = bx.icmp(IntPredicate::IntULT, unsized_align, packed);
+            unsized_align = bx.select(cmp, unsized_align, packed)
+        }
 
         // Bump the unaligned offset up to the appropriate alignment
         let offset = round_up_const_value_to_alignment(bx, unaligned_offset, unsized_align);
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index c0a20e51482..04e5b550d6d 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -282,9 +282,7 @@ impl<'mir, 'tcx, Prov: Provenance, Extra> Frame<'mir, 'tcx, Prov, Extra> {
 impl<'tcx> fmt::Display for FrameInfo<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         ty::tls::with(|tcx| {
-            if tcx.def_key(self.instance.def_id()).disambiguated_data.data
-                == DefPathData::ClosureExpr
-            {
+            if tcx.def_key(self.instance.def_id()).disambiguated_data.data == DefPathData::Closure {
                 write!(f, "inside closure")
             } else {
                 // Note: this triggers a `good_path_delayed_bug` state, which means that if we ever
@@ -299,7 +297,7 @@ impl<'tcx> fmt::Display for FrameInfo<'tcx> {
 impl<'tcx> FrameInfo<'tcx> {
     pub fn as_note(&self, tcx: TyCtxt<'tcx>) -> errors::FrameNote {
         let span = self.span;
-        if tcx.def_key(self.instance.def_id()).disambiguated_data.data == DefPathData::ClosureExpr {
+        if tcx.def_key(self.instance.def_id()).disambiguated_data.data == DefPathData::Closure {
             errors::FrameNote { where_: "closure", span, instance: String::new(), times: 0 }
         } else {
             let instance = format!("{}", self.instance);
diff --git a/compiler/rustc_const_eval/src/interpret/projection.rs b/compiler/rustc_const_eval/src/interpret/projection.rs
index c8977aac0fc..4d9e296d544 100644
--- a/compiler/rustc_const_eval/src/interpret/projection.rs
+++ b/compiler/rustc_const_eval/src/interpret/projection.rs
@@ -163,7 +163,17 @@ where
             // With custom DSTS, this *will* execute user-defined code, but the same
             // happens at run-time so that's okay.
             match self.size_and_align_of(&base_meta, &field_layout)? {
-                Some((_, align)) => (base_meta, offset.align_to(align)),
+                Some((_, align)) => {
+                    // For packed types, we need to cap alignment.
+                    let align = if let ty::Adt(def, _) = base.layout().ty.kind()
+                        && let Some(packed) = def.repr().pack
+                    {
+                        align.min(packed)
+                    } else {
+                        align
+                    };
+                    (base_meta, offset.align_to(align))
+                }
                 None => {
                     // For unsized types with an extern type tail we perform no adjustments.
                     // NOTE: keep this in sync with `PlaceRef::project_field` in the codegen backend.
diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs
index fedd380cada..258d6710bc5 100644
--- a/compiler/rustc_hir/src/def.rs
+++ b/compiler/rustc_hir/src/def.rs
@@ -1,3 +1,4 @@
+use crate::definitions::DefPathData;
 use crate::hir;
 
 use rustc_ast as ast;
@@ -45,6 +46,7 @@ pub enum NonMacroAttrKind {
 }
 
 /// What kind of definition something is; e.g., `mod` vs `struct`.
+/// `enum DefPathData` may need to be updated if a new variant is added here.
 #[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug, HashStable_Generic)]
 pub enum DefKind {
     // Type namespace
@@ -221,6 +223,41 @@ impl DefKind {
         }
     }
 
+    pub fn def_path_data(self, name: Symbol) -> DefPathData {
+        match self {
+            DefKind::Mod
+            | DefKind::Struct
+            | DefKind::Union
+            | DefKind::Enum
+            | DefKind::Variant
+            | DefKind::Trait
+            | DefKind::TyAlias
+            | DefKind::ForeignTy
+            | DefKind::TraitAlias
+            | DefKind::AssocTy
+            | DefKind::TyParam
+            | DefKind::ExternCrate => DefPathData::TypeNs(name),
+            DefKind::Fn
+            | DefKind::Const
+            | DefKind::ConstParam
+            | DefKind::Static(..)
+            | DefKind::AssocFn
+            | DefKind::AssocConst
+            | DefKind::Field => DefPathData::ValueNs(name),
+            DefKind::Macro(..) => DefPathData::MacroNs(name),
+            DefKind::LifetimeParam => DefPathData::LifetimeNs(name),
+            DefKind::Ctor(..) => DefPathData::Ctor,
+            DefKind::Use => DefPathData::Use,
+            DefKind::ForeignMod => DefPathData::ForeignMod,
+            DefKind::AnonConst => DefPathData::AnonConst,
+            DefKind::InlineConst => DefPathData::AnonConst,
+            DefKind::OpaqueTy => DefPathData::OpaqueTy,
+            DefKind::GlobalAsm => DefPathData::GlobalAsm,
+            DefKind::Impl { .. } => DefPathData::Impl,
+            DefKind::Closure => DefPathData::Closure,
+        }
+    }
+
     #[inline]
     pub fn is_fn_like(self) -> bool {
         matches!(self, DefKind::Fn | DefKind::AssocFn | DefKind::Closure)
diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs
index 168b336e374..d222325475d 100644
--- a/compiler/rustc_hir/src/definitions.rs
+++ b/compiler/rustc_hir/src/definitions.rs
@@ -246,6 +246,7 @@ impl DefPath {
     }
 }
 
+/// New variants should only be added in synchronization with `enum DefKind`.
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)]
 pub enum DefPathData {
     // Root: these should only be used for the root nodes, because
@@ -271,7 +272,7 @@ pub enum DefPathData {
     /// Something in the lifetime namespace.
     LifetimeNs(Symbol),
     /// A closure expression.
-    ClosureExpr,
+    Closure,
 
     // Subportions of items:
     /// Implicit constructor for a unit or tuple-like struct or enum variant.
@@ -280,9 +281,7 @@ pub enum DefPathData {
     AnonConst,
     /// An existential `impl Trait` type node.
     /// Argument position `impl Trait` have a `TypeNs` with their pretty-printed name.
-    ImplTrait,
-    /// `impl Trait` generated associated type node.
-    ImplTraitAssocTy,
+    OpaqueTy,
 }
 
 impl Definitions {
@@ -403,16 +402,17 @@ impl DefPathData {
     pub fn get_opt_name(&self) -> Option<Symbol> {
         use self::DefPathData::*;
         match *self {
+            TypeNs(name) if name == kw::Empty => None,
             TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) => Some(name),
-
-            Impl | ForeignMod | CrateRoot | Use | GlobalAsm | ClosureExpr | Ctor | AnonConst
-            | ImplTrait | ImplTraitAssocTy => None,
+            Impl | ForeignMod | CrateRoot | Use | GlobalAsm | Closure | Ctor | AnonConst
+            | OpaqueTy => None,
         }
     }
 
     pub fn name(&self) -> DefPathDataName {
         use self::DefPathData::*;
         match *self {
+            TypeNs(name) if name == kw::Empty => DefPathDataName::Anon { namespace: sym::opaque },
             TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) => {
                 DefPathDataName::Named(name)
             }
@@ -422,10 +422,10 @@ impl DefPathData {
             ForeignMod => DefPathDataName::Anon { namespace: kw::Extern },
             Use => DefPathDataName::Anon { namespace: kw::Use },
             GlobalAsm => DefPathDataName::Anon { namespace: sym::global_asm },
-            ClosureExpr => DefPathDataName::Anon { namespace: sym::closure },
+            Closure => DefPathDataName::Anon { namespace: sym::closure },
             Ctor => DefPathDataName::Anon { namespace: sym::constructor },
             AnonConst => DefPathDataName::Anon { namespace: sym::constant },
-            ImplTrait | ImplTraitAssocTy => DefPathDataName::Anon { namespace: sym::opaque },
+            OpaqueTy => DefPathDataName::Anon { namespace: sym::opaque },
         }
     }
 }
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index ff690db7bee..8e71327f82e 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -977,7 +977,7 @@ impl<'tcx> TyCtxtAt<'tcx> {
     pub fn create_def(
         self,
         parent: LocalDefId,
-        data: hir::definitions::DefPathData,
+        name: Symbol,
         def_kind: DefKind,
     ) -> TyCtxtFeed<'tcx, LocalDefId> {
         // This function modifies `self.definitions` using a side-effect.
@@ -1000,6 +1000,7 @@ impl<'tcx> TyCtxtAt<'tcx> {
         // This is fine because:
         // - those queries are `eval_always` so we won't miss their result changing;
         // - this write will have happened before these queries are called.
+        let data = def_kind.def_path_data(name);
         let key = self.untracked.definitions.write().create_def(parent, data);
 
         let feed = TyCtxtFeed { tcx: self.tcx, key };
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index cebefbccc11..1c7a7545e2b 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -215,7 +215,7 @@ impl<'tcx> InstanceDef<'tcx> {
         };
         matches!(
             tcx.def_key(def_id).disambiguated_data.data,
-            DefPathData::Ctor | DefPathData::ClosureExpr
+            DefPathData::Ctor | DefPathData::Closure
         )
     }
 
diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs
index 64ae11df5b5..5e09154789a 100644
--- a/compiler/rustc_middle/src/ty/print/mod.rs
+++ b/compiler/rustc_middle/src/ty/print/mod.rs
@@ -131,7 +131,7 @@ pub trait Printer<'tcx>: Sized {
 
                     match key.disambiguated_data.data {
                         // Closures' own generics are only captures, don't print them.
-                        DefPathData::ClosureExpr => {}
+                        DefPathData::Closure => {}
                         // This covers both `DefKind::AnonConst` and `DefKind::InlineConst`.
                         // Anon consts doesn't have their own generics, and inline consts' own
                         // generics are their inferred types, so don't print them.
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 68dd8dee87c..25423348638 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -1804,13 +1804,13 @@ impl<'a, 'tcx> FmtPrinter<'a, 'tcx> {
 // (but also some things just print a `DefId` generally so maybe we need this?)
 fn guess_def_namespace(tcx: TyCtxt<'_>, def_id: DefId) -> Namespace {
     match tcx.def_key(def_id).disambiguated_data.data {
-        DefPathData::TypeNs(..) | DefPathData::CrateRoot | DefPathData::ImplTrait => {
+        DefPathData::TypeNs(..) | DefPathData::CrateRoot | DefPathData::OpaqueTy => {
             Namespace::TypeNS
         }
 
         DefPathData::ValueNs(..)
         | DefPathData::AnonConst
-        | DefPathData::ClosureExpr
+        | DefPathData::Closure
         | DefPathData::Ctor => Namespace::ValueNS,
 
         DefPathData::MacroNs(..) => Namespace::MacroNS,
diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs
index 224f3f36a3f..647c92785e1 100644
--- a/compiler/rustc_resolve/src/def_collector.rs
+++ b/compiler/rustc_resolve/src/def_collector.rs
@@ -4,9 +4,8 @@ use rustc_ast::*;
 use rustc_expand::expand::AstFragment;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind};
 use rustc_hir::def_id::LocalDefId;
-use rustc_hir::definitions::*;
 use rustc_span::hygiene::LocalExpnId;
-use rustc_span::symbol::sym;
+use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::Span;
 
 pub(crate) fn collect_definitions(
@@ -30,16 +29,19 @@ impl<'a, 'b, 'tcx> DefCollector<'a, 'b, 'tcx> {
     fn create_def(
         &mut self,
         node_id: NodeId,
-        data: DefPathData,
+        name: Symbol,
         def_kind: DefKind,
         span: Span,
     ) -> LocalDefId {
         let parent_def = self.parent_def;
-        debug!("create_def(node_id={:?}, data={:?}, parent_def={:?})", node_id, data, parent_def);
+        debug!(
+            "create_def(node_id={:?}, def_kind={:?}, parent_def={:?})",
+            node_id, def_kind, parent_def
+        );
         self.resolver.create_def(
             parent_def,
             node_id,
-            data,
+            name,
             def_kind,
             self.expansion.to_expn_id(),
             span.with_parent(None),
@@ -76,8 +78,7 @@ impl<'a, 'b, 'tcx> DefCollector<'a, 'b, 'tcx> {
             self.visit_macro_invoc(field.id);
         } else {
             let name = field.ident.map_or_else(|| sym::integer(index(self)), |ident| ident.name);
-            let def =
-                self.create_def(field.id, DefPathData::ValueNs(name), DefKind::Field, field.span);
+            let def = self.create_def(field.id, name, DefKind::Field, field.span);
             self.with_parent(def, |this| visit::walk_field_def(this, field));
         }
     }
@@ -97,40 +98,36 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
         // Pick the def data. This need not be unique, but the more
         // information we encapsulate into, the better
         let mut opt_macro_data = None;
-        let ty_data = DefPathData::TypeNs(i.ident.name);
-        let value_data = DefPathData::ValueNs(i.ident.name);
-        let (def_data, def_kind) = match &i.kind {
-            ItemKind::Impl(i) => {
-                (DefPathData::Impl, DefKind::Impl { of_trait: i.of_trait.is_some() })
-            }
-            ItemKind::ForeignMod(..) => (DefPathData::ForeignMod, DefKind::ForeignMod),
-            ItemKind::Mod(..) => (ty_data, DefKind::Mod),
-            ItemKind::Trait(..) => (ty_data, DefKind::Trait),
-            ItemKind::TraitAlias(..) => (ty_data, DefKind::TraitAlias),
-            ItemKind::Enum(..) => (ty_data, DefKind::Enum),
-            ItemKind::Struct(..) => (ty_data, DefKind::Struct),
-            ItemKind::Union(..) => (ty_data, DefKind::Union),
-            ItemKind::ExternCrate(..) => (ty_data, DefKind::ExternCrate),
-            ItemKind::TyAlias(..) => (ty_data, DefKind::TyAlias),
-            ItemKind::Static(s) => (value_data, DefKind::Static(s.mutability)),
-            ItemKind::Const(..) => (value_data, DefKind::Const),
-            ItemKind::Fn(..) => (value_data, DefKind::Fn),
+        let def_kind = match &i.kind {
+            ItemKind::Impl(i) => DefKind::Impl { of_trait: i.of_trait.is_some() },
+            ItemKind::ForeignMod(..) => DefKind::ForeignMod,
+            ItemKind::Mod(..) => DefKind::Mod,
+            ItemKind::Trait(..) => DefKind::Trait,
+            ItemKind::TraitAlias(..) => DefKind::TraitAlias,
+            ItemKind::Enum(..) => DefKind::Enum,
+            ItemKind::Struct(..) => DefKind::Struct,
+            ItemKind::Union(..) => DefKind::Union,
+            ItemKind::ExternCrate(..) => DefKind::ExternCrate,
+            ItemKind::TyAlias(..) => DefKind::TyAlias,
+            ItemKind::Static(s) => DefKind::Static(s.mutability),
+            ItemKind::Const(..) => DefKind::Const,
+            ItemKind::Fn(..) => DefKind::Fn,
             ItemKind::MacroDef(..) => {
                 let macro_data = self.resolver.compile_macro(i, self.resolver.tcx.sess.edition());
                 let macro_kind = macro_data.ext.macro_kind();
                 opt_macro_data = Some(macro_data);
-                (DefPathData::MacroNs(i.ident.name), DefKind::Macro(macro_kind))
+                DefKind::Macro(macro_kind)
             }
             ItemKind::MacCall(..) => {
                 visit::walk_item(self, i);
                 return self.visit_macro_invoc(i.id);
             }
-            ItemKind::GlobalAsm(..) => (DefPathData::GlobalAsm, DefKind::GlobalAsm),
+            ItemKind::GlobalAsm(..) => DefKind::GlobalAsm,
             ItemKind::Use(..) => {
                 return visit::walk_item(self, i);
             }
         };
-        let def_id = self.create_def(i.id, def_data, def_kind, i.span);
+        let def_id = self.create_def(i.id, i.ident.name, def_kind, i.span);
 
         if let Some(macro_data) = opt_macro_data {
             self.resolver.macro_map.insert(def_id.to_def_id(), macro_data);
@@ -144,7 +141,7 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
                         if let Some((ctor_kind, ctor_node_id)) = CtorKind::from_ast(struct_def) {
                             this.create_def(
                                 ctor_node_id,
-                                DefPathData::Ctor,
+                                kw::Empty,
                                 DefKind::Ctor(CtorOf::Struct, ctor_kind),
                                 i.span,
                             );
@@ -174,12 +171,8 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
                 // then the closure_def will never be used, and we should avoid generating a
                 // def-id for it.
                 if let Some(body) = body {
-                    let closure_def = self.create_def(
-                        closure_id,
-                        DefPathData::ClosureExpr,
-                        DefKind::Closure,
-                        span,
-                    );
+                    let closure_def =
+                        self.create_def(closure_id, kw::Empty, DefKind::Closure, span);
                     self.with_parent(closure_def, |this| this.visit_block(body));
                 }
                 return;
@@ -190,21 +183,19 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
     }
 
     fn visit_use_tree(&mut self, use_tree: &'a UseTree, id: NodeId, _nested: bool) {
-        self.create_def(id, DefPathData::Use, DefKind::Use, use_tree.span);
+        self.create_def(id, kw::Empty, DefKind::Use, use_tree.span);
         visit::walk_use_tree(self, use_tree, id);
     }
 
     fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
-        let (def_data, def_kind) = match fi.kind {
-            ForeignItemKind::Static(_, mt, _) => {
-                (DefPathData::ValueNs(fi.ident.name), DefKind::Static(mt))
-            }
-            ForeignItemKind::Fn(_) => (DefPathData::ValueNs(fi.ident.name), DefKind::Fn),
-            ForeignItemKind::TyAlias(_) => (DefPathData::TypeNs(fi.ident.name), DefKind::ForeignTy),
+        let def_kind = match fi.kind {
+            ForeignItemKind::Static(_, mt, _) => DefKind::Static(mt),
+            ForeignItemKind::Fn(_) => DefKind::Fn,
+            ForeignItemKind::TyAlias(_) => DefKind::ForeignTy,
             ForeignItemKind::MacCall(_) => return self.visit_macro_invoc(fi.id),
         };
 
-        let def = self.create_def(fi.id, def_data, def_kind, fi.span);
+        let def = self.create_def(fi.id, fi.ident.name, def_kind, fi.span);
 
         self.with_parent(def, |this| visit::walk_foreign_item(this, fi));
     }
@@ -213,13 +204,12 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
         if v.is_placeholder {
             return self.visit_macro_invoc(v.id);
         }
-        let def =
-            self.create_def(v.id, DefPathData::TypeNs(v.ident.name), DefKind::Variant, v.span);
+        let def = self.create_def(v.id, v.ident.name, DefKind::Variant, v.span);
         self.with_parent(def, |this| {
             if let Some((ctor_kind, ctor_node_id)) = CtorKind::from_ast(&v.data) {
                 this.create_def(
                     ctor_node_id,
-                    DefPathData::Ctor,
+                    kw::Empty,
                     DefKind::Ctor(CtorOf::Variant, ctor_kind),
                     v.span,
                 );
@@ -242,15 +232,12 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
             self.visit_macro_invoc(param.id);
             return;
         }
-        let name = param.ident.name;
-        let (def_path_data, def_kind) = match param.kind {
-            GenericParamKind::Lifetime { .. } => {
-                (DefPathData::LifetimeNs(name), DefKind::LifetimeParam)
-            }
-            GenericParamKind::Type { .. } => (DefPathData::TypeNs(name), DefKind::TyParam),
-            GenericParamKind::Const { .. } => (DefPathData::ValueNs(name), DefKind::ConstParam),
+        let def_kind = match param.kind {
+            GenericParamKind::Lifetime { .. } => DefKind::LifetimeParam,
+            GenericParamKind::Type { .. } => DefKind::TyParam,
+            GenericParamKind::Const { .. } => DefKind::ConstParam,
         };
-        self.create_def(param.id, def_path_data, def_kind, param.ident.span);
+        self.create_def(param.id, param.ident.name, def_kind, param.ident.span);
 
         // impl-Trait can happen inside generic parameters, like
         // ```
@@ -264,14 +251,14 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
     }
 
     fn visit_assoc_item(&mut self, i: &'a AssocItem, ctxt: visit::AssocCtxt) {
-        let (def_data, def_kind) = match &i.kind {
-            AssocItemKind::Fn(..) => (DefPathData::ValueNs(i.ident.name), DefKind::AssocFn),
-            AssocItemKind::Const(..) => (DefPathData::ValueNs(i.ident.name), DefKind::AssocConst),
-            AssocItemKind::Type(..) => (DefPathData::TypeNs(i.ident.name), DefKind::AssocTy),
+        let def_kind = match &i.kind {
+            AssocItemKind::Fn(..) => DefKind::AssocFn,
+            AssocItemKind::Const(..) => DefKind::AssocConst,
+            AssocItemKind::Type(..) => DefKind::AssocTy,
             AssocItemKind::MacCall(..) => return self.visit_macro_invoc(i.id),
         };
 
-        let def = self.create_def(i.id, def_data, def_kind, i.span);
+        let def = self.create_def(i.id, i.ident.name, def_kind, i.span);
         self.with_parent(def, |this| visit::walk_assoc_item(this, i, ctxt));
     }
 
@@ -283,12 +270,7 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
     }
 
     fn visit_anon_const(&mut self, constant: &'a AnonConst) {
-        let def = self.create_def(
-            constant.id,
-            DefPathData::AnonConst,
-            DefKind::AnonConst,
-            constant.value.span,
-        );
+        let def = self.create_def(constant.id, kw::Empty, DefKind::AnonConst, constant.value.span);
         self.with_parent(def, |this| visit::walk_anon_const(this, constant));
     }
 
@@ -298,25 +280,21 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
             ExprKind::Closure(ref closure) => {
                 // Async closures desugar to closures inside of closures, so
                 // we must create two defs.
-                let closure_def =
-                    self.create_def(expr.id, DefPathData::ClosureExpr, DefKind::Closure, expr.span);
+                let closure_def = self.create_def(expr.id, kw::Empty, DefKind::Closure, expr.span);
                 match closure.asyncness {
-                    Async::Yes { closure_id, .. } => self.create_def(
-                        closure_id,
-                        DefPathData::ClosureExpr,
-                        DefKind::Closure,
-                        expr.span,
-                    ),
+                    Async::Yes { closure_id, .. } => {
+                        self.create_def(closure_id, kw::Empty, DefKind::Closure, expr.span)
+                    }
                     Async::No => closure_def,
                 }
             }
             ExprKind::Gen(_, _, _) => {
-                self.create_def(expr.id, DefPathData::ClosureExpr, DefKind::Closure, expr.span)
+                self.create_def(expr.id, kw::Empty, DefKind::Closure, expr.span)
             }
             ExprKind::ConstBlock(ref constant) => {
                 let def = self.create_def(
                     constant.id,
-                    DefPathData::AnonConst,
+                    kw::Empty,
                     DefKind::InlineConst,
                     constant.value.span,
                 );
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 208391cc019..70e0eb12c01 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -45,7 +45,6 @@ use rustc_hir::def::NonMacroAttrKind;
 use rustc_hir::def::{self, CtorOf, DefKind, DocLinkResMap, LifetimeRes, PartialRes, PerNS};
 use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap, LocalDefIdSet};
 use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE};
-use rustc_hir::definitions::DefPathData;
 use rustc_hir::{PrimTy, TraitCandidate};
 use rustc_index::IndexVec;
 use rustc_metadata::creader::{CStore, CrateLoader};
@@ -1212,11 +1211,12 @@ impl<'tcx> Resolver<'_, 'tcx> {
         &mut self,
         parent: LocalDefId,
         node_id: ast::NodeId,
-        data: DefPathData,
+        name: Symbol,
         def_kind: DefKind,
         expn_id: ExpnId,
         span: Span,
     ) -> LocalDefId {
+        let data = def_kind.def_path_data(name);
         assert!(
             !self.node_id_to_def_id.contains_key(&node_id),
             "adding a def'n for node-id {:?} and data {:?} but a previous def'n exists: {:?}",
diff --git a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
index 1fd8542b2a6..18ca347de97 100644
--- a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
+++ b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
@@ -379,14 +379,13 @@ fn encode_ty_name(tcx: TyCtxt<'_>, def_id: DefId) -> String {
             hir::definitions::DefPathData::ForeignMod => "F", // Not specified in v0's <namespace>
             hir::definitions::DefPathData::TypeNs(..) => "t",
             hir::definitions::DefPathData::ValueNs(..) => "v",
-            hir::definitions::DefPathData::ClosureExpr => "C",
+            hir::definitions::DefPathData::Closure => "C",
             hir::definitions::DefPathData::Ctor => "c",
             hir::definitions::DefPathData::AnonConst => "k",
-            hir::definitions::DefPathData::ImplTrait => "i",
+            hir::definitions::DefPathData::OpaqueTy => "i",
             hir::definitions::DefPathData::CrateRoot
             | hir::definitions::DefPathData::Use
             | hir::definitions::DefPathData::GlobalAsm
-            | hir::definitions::DefPathData::ImplTraitAssocTy
             | hir::definitions::DefPathData::MacroNs(..)
             | hir::definitions::DefPathData::LifetimeNs(..) => {
                 bug!("encode_ty_name: unexpected `{:?}`", disambiguated_data.data);
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index 88989806997..e002e345ae6 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -770,17 +770,16 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
             // Uppercase categories are more stable than lowercase ones.
             DefPathData::TypeNs(_) => 't',
             DefPathData::ValueNs(_) => 'v',
-            DefPathData::ClosureExpr => 'C',
+            DefPathData::Closure => 'C',
             DefPathData::Ctor => 'c',
             DefPathData::AnonConst => 'k',
-            DefPathData::ImplTrait => 'i',
+            DefPathData::OpaqueTy => 'i',
 
             // These should never show up as `path_append` arguments.
             DefPathData::CrateRoot
             | DefPathData::Use
             | DefPathData::GlobalAsm
             | DefPathData::Impl
-            | DefPathData::ImplTraitAssocTy
             | DefPathData::MacroNs(_)
             | DefPathData::LifetimeNs(_) => {
                 bug!("symbol_names: unexpected DefPathData: {:?}", disambiguated_data.data)
diff --git a/compiler/rustc_trait_selection/messages.ftl b/compiler/rustc_trait_selection/messages.ftl
index d753aa8618e..41db8059cbe 100644
--- a/compiler/rustc_trait_selection/messages.ftl
+++ b/compiler/rustc_trait_selection/messages.ftl
@@ -55,3 +55,6 @@ trait_selection_trait_has_no_impls = this trait has no implementations, consider
 
 trait_selection_ty_alias_overflow = in case this is a recursive type alias, consider using a struct, enum, or union instead
 trait_selection_unable_to_construct_constant_value = unable to construct a constant value for the unevaluated constant {$unevaluated}
+
+trait_selection_unknown_format_parameter_for_on_unimplemented_attr = there is no parameter `{$argument_name}` on trait `{$trait_name}`
+    .help = expect either a generic argument name or {"`{Self}`"} as format argument
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
index ba019c4ff6f..fbe6e2bd5b8 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
@@ -321,7 +321,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
 }
 
 #[derive(Clone, Debug)]
-pub struct OnUnimplementedFormatString(Symbol, Span);
+pub struct OnUnimplementedFormatString {
+    symbol: Symbol,
+    span: Span,
+    is_diagnostic_namespace_variant: bool,
+}
 
 #[derive(Debug)]
 pub struct OnUnimplementedDirective {
@@ -401,6 +405,14 @@ impl IgnoredDiagnosticOption {
     }
 }
 
+#[derive(LintDiagnostic)]
+#[diag(trait_selection_unknown_format_parameter_for_on_unimplemented_attr)]
+#[help]
+pub struct UnknownFormatParameterForOnUnimplementedAttr {
+    argument_name: Symbol,
+    trait_name: Symbol,
+}
+
 impl<'tcx> OnUnimplementedDirective {
     fn parse(
         tcx: TyCtxt<'tcx>,
@@ -414,8 +426,14 @@ impl<'tcx> OnUnimplementedDirective {
         let mut item_iter = items.iter();
 
         let parse_value = |value_str, value_span| {
-            OnUnimplementedFormatString::try_parse(tcx, item_def_id, value_str, span, value_span)
-                .map(Some)
+            OnUnimplementedFormatString::try_parse(
+                tcx,
+                item_def_id,
+                value_str,
+                value_span,
+                is_diagnostic_namespace_variant,
+            )
+            .map(Some)
         };
 
         let condition = if is_root {
@@ -552,15 +570,15 @@ impl<'tcx> OnUnimplementedDirective {
                         IgnoredDiagnosticOption::maybe_emit_warning(
                             tcx,
                             item_def_id,
-                            directive.message.as_ref().map(|f| f.1),
-                            aggr.message.as_ref().map(|f| f.1),
+                            directive.message.as_ref().map(|f| f.span),
+                            aggr.message.as_ref().map(|f| f.span),
                             "message",
                         );
                         IgnoredDiagnosticOption::maybe_emit_warning(
                             tcx,
                             item_def_id,
-                            directive.label.as_ref().map(|f| f.1),
-                            aggr.label.as_ref().map(|f| f.1),
+                            directive.label.as_ref().map(|f| f.span),
+                            aggr.label.as_ref().map(|f| f.span),
                             "label",
                         );
                         IgnoredDiagnosticOption::maybe_emit_warning(
@@ -573,8 +591,8 @@ impl<'tcx> OnUnimplementedDirective {
                         IgnoredDiagnosticOption::maybe_emit_warning(
                             tcx,
                             item_def_id,
-                            directive.parent_label.as_ref().map(|f| f.1),
-                            aggr.parent_label.as_ref().map(|f| f.1),
+                            directive.parent_label.as_ref().map(|f| f.span),
+                            aggr.parent_label.as_ref().map(|f| f.span),
                             "parent_label",
                         );
                         IgnoredDiagnosticOption::maybe_emit_warning(
@@ -634,7 +652,7 @@ impl<'tcx> OnUnimplementedDirective {
                         item_def_id,
                         value,
                         attr.span,
-                        attr.span,
+                        is_diagnostic_namespace_variant,
                     )?),
                     notes: Vec::new(),
                     parent_label: None,
@@ -713,7 +731,12 @@ impl<'tcx> OnUnimplementedDirective {
                             // `with_no_visible_paths` is also used when generating the options,
                             // so we need to match it here.
                             ty::print::with_no_visible_paths!(
-                                OnUnimplementedFormatString(v, cfg.span).format(
+                                OnUnimplementedFormatString {
+                                    symbol: v,
+                                    span: cfg.span,
+                                    is_diagnostic_namespace_variant: false
+                                }
+                                .format(
                                     tcx,
                                     trait_ref,
                                     &options_map
@@ -761,20 +784,19 @@ impl<'tcx> OnUnimplementedFormatString {
         tcx: TyCtxt<'tcx>,
         item_def_id: DefId,
         from: Symbol,
-        err_sp: Span,
         value_span: Span,
+        is_diagnostic_namespace_variant: bool,
     ) -> Result<Self, ErrorGuaranteed> {
-        let result = OnUnimplementedFormatString(from, value_span);
-        result.verify(tcx, item_def_id, err_sp)?;
+        let result = OnUnimplementedFormatString {
+            symbol: from,
+            span: value_span,
+            is_diagnostic_namespace_variant,
+        };
+        result.verify(tcx, item_def_id)?;
         Ok(result)
     }
 
-    fn verify(
-        &self,
-        tcx: TyCtxt<'tcx>,
-        item_def_id: DefId,
-        span: Span,
-    ) -> Result<(), ErrorGuaranteed> {
+    fn verify(&self, tcx: TyCtxt<'tcx>, item_def_id: DefId) -> Result<(), ErrorGuaranteed> {
         let trait_def_id = if tcx.is_trait(item_def_id) {
             item_def_id
         } else {
@@ -783,7 +805,7 @@ impl<'tcx> OnUnimplementedFormatString {
         };
         let trait_name = tcx.item_name(trait_def_id);
         let generics = tcx.generics_of(item_def_id);
-        let s = self.0.as_str();
+        let s = self.symbol.as_str();
         let parser = Parser::new(s, None, None, false, ParseMode::Format);
         let mut result = Ok(());
         for token in parser {
@@ -793,24 +815,40 @@ impl<'tcx> OnUnimplementedFormatString {
                     Position::ArgumentNamed(s) => {
                         match Symbol::intern(s) {
                             // `{ThisTraitsName}` is allowed
-                            s if s == trait_name => (),
-                            s if ALLOWED_FORMAT_SYMBOLS.contains(&s) => (),
+                            s if s == trait_name && !self.is_diagnostic_namespace_variant => (),
+                            s if ALLOWED_FORMAT_SYMBOLS.contains(&s)
+                                && !self.is_diagnostic_namespace_variant =>
+                            {
+                                ()
+                            }
                             // So is `{A}` if A is a type parameter
                             s if generics.params.iter().any(|param| param.name == s) => (),
                             s => {
-                                result = Err(struct_span_err!(
-                                    tcx.sess,
-                                    span,
-                                    E0230,
-                                    "there is no parameter `{}` on {}",
-                                    s,
-                                    if trait_def_id == item_def_id {
-                                        format!("trait `{trait_name}`")
-                                    } else {
-                                        "impl".to_string()
-                                    }
-                                )
-                                .emit());
+                                if self.is_diagnostic_namespace_variant {
+                                    tcx.emit_spanned_lint(
+                                        UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
+                                        tcx.local_def_id_to_hir_id(item_def_id.expect_local()),
+                                        self.span,
+                                        UnknownFormatParameterForOnUnimplementedAttr {
+                                            argument_name: s,
+                                            trait_name,
+                                        },
+                                    );
+                                } else {
+                                    result = Err(struct_span_err!(
+                                        tcx.sess,
+                                        self.span,
+                                        E0230,
+                                        "there is no parameter `{}` on {}",
+                                        s,
+                                        if trait_def_id == item_def_id {
+                                            format!("trait `{trait_name}`")
+                                        } else {
+                                            "impl".to_string()
+                                        }
+                                    )
+                                    .emit());
+                                }
                             }
                         }
                     }
@@ -818,7 +856,7 @@ impl<'tcx> OnUnimplementedFormatString {
                     Position::ArgumentIs(..) | Position::ArgumentImplicitlyIs(_) => {
                         let reported = struct_span_err!(
                             tcx.sess,
-                            span,
+                            self.span,
                             E0231,
                             "only named substitution parameters are allowed"
                         )
@@ -857,37 +895,42 @@ impl<'tcx> OnUnimplementedFormatString {
             .collect::<FxHashMap<Symbol, String>>();
         let empty_string = String::new();
 
-        let s = self.0.as_str();
+        let s = self.symbol.as_str();
         let parser = Parser::new(s, None, None, false, ParseMode::Format);
         let item_context = (options.get(&sym::ItemContext)).unwrap_or(&empty_string);
         parser
             .map(|p| match p {
-                Piece::String(s) => s,
+                Piece::String(s) => s.to_owned(),
                 Piece::NextArgument(a) => match a.position {
-                    Position::ArgumentNamed(s) => {
-                        let s = Symbol::intern(s);
+                    Position::ArgumentNamed(arg) => {
+                        let s = Symbol::intern(arg);
                         match generic_map.get(&s) {
-                            Some(val) => val,
-                            None if s == name => &trait_str,
+                            Some(val) => val.to_string(),
+                            None if self.is_diagnostic_namespace_variant => {
+                                format!("{{{arg}}}")
+                            }
+                            None if s == name => trait_str.clone(),
                             None => {
                                 if let Some(val) = options.get(&s) {
-                                    val
+                                    val.clone()
                                 } else if s == sym::from_desugaring {
                                     // don't break messages using these two arguments incorrectly
-                                    &empty_string
-                                } else if s == sym::ItemContext {
-                                    item_context
+                                    String::new()
+                                } else if s == sym::ItemContext
+                                    && !self.is_diagnostic_namespace_variant
+                                {
+                                    item_context.clone()
                                 } else if s == sym::integral {
-                                    "{integral}"
+                                    String::from("{integral}")
                                 } else if s == sym::integer_ {
-                                    "{integer}"
+                                    String::from("{integer}")
                                 } else if s == sym::float {
-                                    "{float}"
+                                    String::from("{float}")
                                 } else {
                                     bug!(
                                         "broken on_unimplemented {:?} for {:?}: \
                                       no argument matching {:?}",
-                                        self.0,
+                                        self.symbol,
                                         trait_ref,
                                         s
                                     )
@@ -895,7 +938,7 @@ impl<'tcx> OnUnimplementedFormatString {
                             }
                         }
                     }
-                    _ => bug!("broken on_unimplemented {:?} - bad format arg", self.0),
+                    _ => bug!("broken on_unimplemented {:?} - bad format arg", self.symbol),
                 },
             })
             .collect()
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
index c6ff7e2a9ef..b28e3d5c412 100644
--- a/compiler/rustc_ty_utils/src/abi.rs
+++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -424,11 +424,23 @@ fn fn_abi_sanity_check<'tcx>(
             }
             PassMode::Indirect { meta_attrs: None, .. } => {
                 // No metadata, must be sized.
+                // Conceptually, unsized arguments must be copied around, which requires dynamically
+                // determining their size, which we cannot do without metadata. Consult
+                // t-opsem before removing this check.
                 assert!(arg.layout.is_sized());
             }
             PassMode::Indirect { meta_attrs: Some(_), on_stack, .. } => {
                 // With metadata. Must be unsized and not on the stack.
                 assert!(arg.layout.is_unsized() && !on_stack);
+                // Also, must not be `extern` type.
+                let tail = cx.tcx.struct_tail_with_normalize(arg.layout.ty, |ty| ty, || {});
+                if matches!(tail.kind(), ty::Foreign(..)) {
+                    // These types do not have metadata, so having `meta_attrs` is bogus.
+                    // Conceptually, unsized arguments must be copied around, which requires dynamically
+                    // determining their size. Therefore, we cannot allow `extern` types here. Consult
+                    // t-opsem before removing this check.
+                    panic!("unsized arguments must not be `extern` types");
+                }
             }
         }
     }
diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs
index 82cd0cc50d2..7a81570e55b 100644
--- a/compiler/rustc_ty_utils/src/assoc.rs
+++ b/compiler/rustc_ty_utils/src/assoc.rs
@@ -2,7 +2,6 @@ use rustc_data_structures::fx::FxIndexSet;
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId};
-use rustc_hir::definitions::DefPathData;
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, GenericArgs, ImplTraitInTraitData, Ty, TyCtxt};
@@ -254,8 +253,7 @@ fn associated_type_for_impl_trait_in_trait(
     assert_eq!(tcx.def_kind(trait_def_id), DefKind::Trait);
 
     let span = tcx.def_span(opaque_ty_def_id);
-    let trait_assoc_ty =
-        tcx.at(span).create_def(trait_def_id, DefPathData::ImplTraitAssocTy, DefKind::AssocTy);
+    let trait_assoc_ty = tcx.at(span).create_def(trait_def_id, kw::Empty, DefKind::AssocTy);
 
     let local_def_id = trait_assoc_ty.def_id();
     let def_id = local_def_id.to_def_id();
@@ -356,8 +354,7 @@ fn associated_type_for_impl_trait_in_impl(
         hir::FnRetTy::DefaultReturn(_) => tcx.def_span(impl_fn_def_id),
         hir::FnRetTy::Return(ty) => ty.span,
     };
-    let impl_assoc_ty =
-        tcx.at(span).create_def(impl_local_def_id, DefPathData::ImplTraitAssocTy, DefKind::AssocTy);
+    let impl_assoc_ty = tcx.at(span).create_def(impl_local_def_id, kw::Empty, DefKind::AssocTy);
 
     let local_def_id = impl_assoc_ty.def_id();
     let def_id = local_def_id.to_def_id();
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index 5957f9fd443..dec9f194863 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -1045,11 +1045,11 @@ impl<T> [T] {
     /// # Examples
     ///
     /// ```
-    /// let slice = ['r', 'u', 's', 't'];
-    /// let mut iter = slice.windows(2);
-    /// assert_eq!(iter.next().unwrap(), &['r', 'u']);
-    /// assert_eq!(iter.next().unwrap(), &['u', 's']);
-    /// assert_eq!(iter.next().unwrap(), &['s', 't']);
+    /// let slice = ['l', 'o', 'r', 'e', 'm'];
+    /// let mut iter = slice.windows(3);
+    /// assert_eq!(iter.next().unwrap(), &['l', 'o', 'r']);
+    /// assert_eq!(iter.next().unwrap(), &['o', 'r', 'e']);
+    /// assert_eq!(iter.next().unwrap(), &['r', 'e', 'm']);
     /// assert!(iter.next().is_none());
     /// ```
     ///
diff --git a/src/tools/miri/tests/pass/issues/issue-3200-packed-field-offset.rs b/src/tools/miri/tests/pass/issues/issue-3200-packed-field-offset.rs
new file mode 100644
index 00000000000..e58fe60b5f6
--- /dev/null
+++ b/src/tools/miri/tests/pass/issues/issue-3200-packed-field-offset.rs
@@ -0,0 +1,35 @@
+#![feature(layout_for_ptr)]
+use std::mem;
+
+#[repr(packed, C)]
+struct PackedSized {
+    f: u8,
+    d: [u32; 4],
+}
+
+#[repr(packed, C)]
+struct PackedUnsized {
+    f: u8,
+    d: [u32],
+}
+
+impl PackedSized {
+    fn unsize(&self) -> &PackedUnsized {
+        // We can't unsize via a generic type since then we get the error
+        // that packed structs with unsized tail don't work if the tail
+        // might need dropping.
+        let len = 4usize;
+        unsafe { mem::transmute((self, len)) }
+    }
+}
+
+fn main() { unsafe {
+    let p = PackedSized { f: 0, d: [1, 2, 3, 4] };
+    let p = p.unsize() as *const PackedUnsized;
+    // Make sure the size computation does *not* think there is
+    // any padding in front of the `d` field.
+    assert_eq!(mem::size_of_val_raw(p), 1 + 4*4);
+    // And likewise for the offset computation.
+    let d = std::ptr::addr_of!((*p).d);
+    assert_eq!(d.cast::<u32>().read_unaligned(), 1);
+} }
diff --git a/src/tools/miri/tests/pass/issues/issue-3200-packed2-field-offset.rs b/src/tools/miri/tests/pass/issues/issue-3200-packed2-field-offset.rs
new file mode 100644
index 00000000000..910b5d94320
--- /dev/null
+++ b/src/tools/miri/tests/pass/issues/issue-3200-packed2-field-offset.rs
@@ -0,0 +1,38 @@
+#![feature(layout_for_ptr)]
+use std::mem;
+
+#[repr(packed(4))]
+struct Slice([u32]);
+
+#[repr(packed(2), C)]
+struct PackedSized {
+    f: u8,
+    d: [u32; 4],
+}
+
+#[repr(packed(2), C)]
+struct PackedUnsized {
+    f: u8,
+    d: Slice,
+}
+
+impl PackedSized {
+    fn unsize(&self) -> &PackedUnsized {
+        // We can't unsize via a generic type since then we get the error
+        // that packed structs with unsized tail don't work if the tail
+        // might need dropping.
+        let len = 4usize;
+        unsafe { mem::transmute((self, len)) }
+    }
+}
+
+fn main() { unsafe {
+    let p = PackedSized { f: 0, d: [1, 2, 3, 4] };
+    let p = p.unsize() as *const PackedUnsized;
+    // Make sure the size computation correctly adds exact 1 byte of padding
+    // in front of the `d` field.
+    assert_eq!(mem::size_of_val_raw(p), 1 + 1 + 4*4);
+    // And likewise for the offset computation.
+    let d = std::ptr::addr_of!((*p).d);
+    assert_eq!(d.cast::<u32>().read_unaligned(), 1);
+} }
diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.rs b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.rs
new file mode 100644
index 00000000000..eb985c062f3
--- /dev/null
+++ b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.rs
@@ -0,0 +1,67 @@
+#![feature(diagnostic_namespace)]
+
+#[diagnostic::on_unimplemented(
+    on(_Self = "&str"),
+    //~^WARN malformed `on_unimplemented` attribute
+    //~|WARN malformed `on_unimplemented` attribute
+    message = "trait has `{Self}` and `{T}` as params",
+    label = "trait has `{Self}` and `{T}` as params",
+    note  = "trait has `{Self}` and `{T}` as params",
+    parent_label = "in this scope",
+    //~^WARN malformed `on_unimplemented` attribute
+    //~|WARN malformed `on_unimplemented` attribute
+    append_const_msg
+    //~^WARN malformed `on_unimplemented` attribute
+    //~|WARN malformed `on_unimplemented` attribute
+)]
+trait Foo<T> {}
+
+#[diagnostic::on_unimplemented = "Message"]
+//~^WARN malformed `on_unimplemented` attribute
+//~|WARN malformed `on_unimplemented` attribute
+trait Bar {}
+
+#[diagnostic::on_unimplemented(message = "Not allowed to apply it on a impl")]
+//~^WARN #[diagnostic::on_unimplemented]` can only be applied to trait definitions
+impl Bar for i32 {}
+
+// cannot use special rustc_on_unimplement symbols
+// in the format string
+#[diagnostic::on_unimplemented(
+    message = "{from_desugaring}{direct}{cause}{integral}{integer}",
+    //~^WARN there is no parameter `from_desugaring` on trait `Baz`
+    //~|WARN there is no parameter `from_desugaring` on trait `Baz`
+    //~|WARN there is no parameter `direct` on trait `Baz`
+    //~|WARN there is no parameter `direct` on trait `Baz`
+    //~|WARN there is no parameter `cause` on trait `Baz`
+    //~|WARN there is no parameter `cause` on trait `Baz`
+    //~|WARN there is no parameter `integral` on trait `Baz`
+    //~|WARN there is no parameter `integral` on trait `Baz`
+    //~|WARN there is no parameter `integer` on trait `Baz`
+    //~|WARN there is no parameter `integer` on trait `Baz`
+    label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
+    //~^WARN there is no parameter `float` on trait `Baz`
+    //~|WARN there is no parameter `float` on trait `Baz`
+    //~|WARN there is no parameter `_Self` on trait `Baz`
+    //~|WARN there is no parameter `_Self` on trait `Baz`
+    //~|WARN there is no parameter `crate_local` on trait `Baz`
+    //~|WARN there is no parameter `crate_local` on trait `Baz`
+    //~|WARN there is no parameter `Trait` on trait `Baz`
+    //~|WARN there is no parameter `Trait` on trait `Baz`
+    //~|WARN there is no parameter `ItemContext` on trait `Baz`
+    //~|WARN there is no parameter `ItemContext` on trait `Baz`
+)]
+trait Baz {}
+
+fn takes_foo(_: impl Foo<i32>) {}
+fn takes_bar(_: impl Bar) {}
+fn takes_baz(_: impl Baz) {}
+
+fn main() {
+    takes_foo(());
+    //~^ERROR trait has `()` and `i32` as params
+    takes_bar(());
+    //~^ERROR the trait bound `(): Bar` is not satisfied
+    takes_baz(());
+    //~^ERROR {from_desugaring}{direct}{cause}{integral}{integer}
+}
diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.stderr
new file mode 100644
index 00000000000..75a701f0b5f
--- /dev/null
+++ b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.stderr
@@ -0,0 +1,305 @@
+warning: `#[diagnostic::on_unimplemented]` can only be applied to trait definitions
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:24:1
+   |
+LL | #[diagnostic::on_unimplemented(message = "Not allowed to apply it on a impl")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default
+
+warning: malformed `on_unimplemented` attribute
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:4:5
+   |
+LL |     on(_Self = "&str"),
+   |     ^^^^^^^^^^^^^^^^^^ invalid option found here
+   |
+   = help: only `message`, `note` and `label` are allowed as options
+
+warning: malformed `on_unimplemented` attribute
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:10:5
+   |
+LL |     parent_label = "in this scope",
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid option found here
+   |
+   = help: only `message`, `note` and `label` are allowed as options
+
+warning: malformed `on_unimplemented` attribute
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:13:5
+   |
+LL |     append_const_msg
+   |     ^^^^^^^^^^^^^^^^ invalid option found here
+   |
+   = help: only `message`, `note` and `label` are allowed as options
+
+warning: malformed `on_unimplemented` attribute
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:19:32
+   |
+LL | #[diagnostic::on_unimplemented = "Message"]
+   |                                ^^^^^^^^^^^ invalid option found here
+   |
+   = help: only `message`, `note` and `label` are allowed as options
+
+warning: there is no parameter `from_desugaring` on trait `Baz`
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5
+   |
+LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: expect either a generic argument name or `{Self}` as format argument
+
+warning: there is no parameter `direct` on trait `Baz`
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5
+   |
+LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: expect either a generic argument name or `{Self}` as format argument
+
+warning: there is no parameter `cause` on trait `Baz`
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5
+   |
+LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: expect either a generic argument name or `{Self}` as format argument
+
+warning: there is no parameter `integral` on trait `Baz`
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5
+   |
+LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: expect either a generic argument name or `{Self}` as format argument
+
+warning: there is no parameter `integer` on trait `Baz`
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5
+   |
+LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: expect either a generic argument name or `{Self}` as format argument
+
+warning: there is no parameter `float` on trait `Baz`
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5
+   |
+LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: expect either a generic argument name or `{Self}` as format argument
+
+warning: there is no parameter `_Self` on trait `Baz`
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5
+   |
+LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: expect either a generic argument name or `{Self}` as format argument
+
+warning: there is no parameter `crate_local` on trait `Baz`
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5
+   |
+LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: expect either a generic argument name or `{Self}` as format argument
+
+warning: there is no parameter `Trait` on trait `Baz`
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5
+   |
+LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: expect either a generic argument name or `{Self}` as format argument
+
+warning: there is no parameter `ItemContext` on trait `Baz`
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5
+   |
+LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: expect either a generic argument name or `{Self}` as format argument
+
+warning: malformed `on_unimplemented` attribute
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:4:5
+   |
+LL |     on(_Self = "&str"),
+   |     ^^^^^^^^^^^^^^^^^^ invalid option found here
+   |
+   = help: only `message`, `note` and `label` are allowed as options
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+warning: malformed `on_unimplemented` attribute
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:10:5
+   |
+LL |     parent_label = "in this scope",
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid option found here
+   |
+   = help: only `message`, `note` and `label` are allowed as options
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+warning: malformed `on_unimplemented` attribute
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:13:5
+   |
+LL |     append_const_msg
+   |     ^^^^^^^^^^^^^^^^ invalid option found here
+   |
+   = help: only `message`, `note` and `label` are allowed as options
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error[E0277]: trait has `()` and `i32` as params
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:61:15
+   |
+LL |     takes_foo(());
+   |     --------- ^^ trait has `()` and `i32` as params
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `Foo<i32>` is not implemented for `()`
+   = note: trait has `()` and `i32` as params
+help: this trait has no implementations, consider adding one
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:17:1
+   |
+LL | trait Foo<T> {}
+   | ^^^^^^^^^^^^
+note: required by a bound in `takes_foo`
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:56:22
+   |
+LL | fn takes_foo(_: impl Foo<i32>) {}
+   |                      ^^^^^^^^ required by this bound in `takes_foo`
+
+warning: malformed `on_unimplemented` attribute
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:19:32
+   |
+LL | #[diagnostic::on_unimplemented = "Message"]
+   |                                ^^^^^^^^^^^ invalid option found here
+   |
+   = help: only `message`, `note` and `label` are allowed as options
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error[E0277]: the trait bound `(): Bar` is not satisfied
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:63:15
+   |
+LL |     takes_bar(());
+   |     --------- ^^ the trait `Bar` is not implemented for `()`
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `Bar` is implemented for `i32`
+note: required by a bound in `takes_bar`
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:57:22
+   |
+LL | fn takes_bar(_: impl Bar) {}
+   |                      ^^^ required by this bound in `takes_bar`
+
+warning: there is no parameter `from_desugaring` on trait `Baz`
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5
+   |
+LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: expect either a generic argument name or `{Self}` as format argument
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+warning: there is no parameter `direct` on trait `Baz`
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5
+   |
+LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: expect either a generic argument name or `{Self}` as format argument
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+warning: there is no parameter `cause` on trait `Baz`
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5
+   |
+LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: expect either a generic argument name or `{Self}` as format argument
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+warning: there is no parameter `integral` on trait `Baz`
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5
+   |
+LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: expect either a generic argument name or `{Self}` as format argument
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+warning: there is no parameter `integer` on trait `Baz`
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5
+   |
+LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: expect either a generic argument name or `{Self}` as format argument
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+warning: there is no parameter `float` on trait `Baz`
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5
+   |
+LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: expect either a generic argument name or `{Self}` as format argument
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+warning: there is no parameter `_Self` on trait `Baz`
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5
+   |
+LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: expect either a generic argument name or `{Self}` as format argument
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+warning: there is no parameter `crate_local` on trait `Baz`
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5
+   |
+LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: expect either a generic argument name or `{Self}` as format argument
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+warning: there is no parameter `Trait` on trait `Baz`
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5
+   |
+LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: expect either a generic argument name or `{Self}` as format argument
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+warning: there is no parameter `ItemContext` on trait `Baz`
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5
+   |
+LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: expect either a generic argument name or `{Self}` as format argument
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error[E0277]: {from_desugaring}{direct}{cause}{integral}{integer}
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:65:15
+   |
+LL |     takes_baz(());
+   |     --------- ^^ {float}{_Self}{crate_local}{Trait}{ItemContext}
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `Baz` is not implemented for `()`
+help: this trait has no implementations, consider adding one
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:54:1
+   |
+LL | trait Baz {}
+   | ^^^^^^^^^
+note: required by a bound in `takes_baz`
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:58:22
+   |
+LL | fn takes_baz(_: impl Baz) {}
+   |                      ^^^ required by this bound in `takes_baz`
+
+error: aborting due to 3 previous errors; 29 warnings emitted
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.rs b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.rs
index 346d8373f73..12fe988170a 100644
--- a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.rs
+++ b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.rs
@@ -28,10 +28,16 @@ trait Doom {}
 //~|WARN missing options for `on_unimplemented` attribute
 trait Whatever {}
 
+#[diagnostic::on_unimplemented(message = "{DoesNotExist}")]
+//~^WARN there is no parameter `DoesNotExist` on trait `Test`
+//~|WARN there is no parameter `DoesNotExist` on trait `Test`
+trait Test {}
+
 fn take_foo(_: impl Foo) {}
 fn take_baz(_: impl Baz) {}
 fn take_boom(_: impl Boom) {}
 fn take_whatever(_: impl Whatever) {}
+fn take_test(_: impl Test) {}
 
 fn main() {
     take_foo(1_i32);
@@ -42,4 +48,6 @@ fn main() {
     //~^ERROR Boom
     take_whatever(1_i32);
     //~^ERROR the trait bound `i32: Whatever` is not satisfied
+    take_test(());
+    //~^ERROR {DoesNotExist}
 }
diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.stderr
index 162ddd79fbb..11263580b15 100644
--- a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.stderr
+++ b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.stderr
@@ -46,6 +46,14 @@ LL | #[diagnostic::on_unimplemented]
    |
    = help: at least one of the `message`, `note` and `label` options are expected
 
+warning: there is no parameter `DoesNotExist` on trait `Test`
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:31:32
+   |
+LL | #[diagnostic::on_unimplemented(message = "{DoesNotExist}")]
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: expect either a generic argument name or `{Self}` as format argument
+
 warning: malformed `on_unimplemented` attribute
   --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:3:32
    |
@@ -56,7 +64,7 @@ LL | #[diagnostic::on_unimplemented(unsupported = "foo")]
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0277]: the trait bound `i32: Foo` is not satisfied
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:37:14
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:43:14
    |
 LL |     take_foo(1_i32);
    |     -------- ^^^^^ the trait `Foo` is not implemented for `i32`
@@ -69,7 +77,7 @@ help: this trait has no implementations, consider adding one
 LL | trait Foo {}
    | ^^^^^^^^^
 note: required by a bound in `take_foo`
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:31:21
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:36:21
    |
 LL | fn take_foo(_: impl Foo) {}
    |                     ^^^ required by this bound in `take_foo`
@@ -84,7 +92,7 @@ LL | #[diagnostic::on_unimplemented(message = "Boom", unsupported = "Bar")]
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0277]: Boom
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:39:14
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:45:14
    |
 LL |     take_baz(1_i32);
    |     -------- ^^^^^ the trait `Baz` is not implemented for `i32`
@@ -97,7 +105,7 @@ help: this trait has no implementations, consider adding one
 LL | trait Baz {}
    | ^^^^^^^^^
 note: required by a bound in `take_baz`
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:32:21
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:37:21
    |
 LL | fn take_baz(_: impl Baz) {}
    |                     ^^^ required by this bound in `take_baz`
@@ -112,7 +120,7 @@ LL | #[diagnostic::on_unimplemented(message = "Boom", on(_Self = "i32", message
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0277]: Boom
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:41:15
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:47:15
    |
 LL |     take_boom(1_i32);
    |     --------- ^^^^^ the trait `Boom` is not implemented for `i32`
@@ -125,7 +133,7 @@ help: this trait has no implementations, consider adding one
 LL | trait Boom {}
    | ^^^^^^^^^^
 note: required by a bound in `take_boom`
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:33:22
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:38:22
    |
 LL | fn take_boom(_: impl Boom) {}
    |                      ^^^^ required by this bound in `take_boom`
@@ -140,7 +148,7 @@ LL | #[diagnostic::on_unimplemented]
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0277]: the trait bound `i32: Whatever` is not satisfied
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:43:19
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:49:19
    |
 LL |     take_whatever(1_i32);
    |     ------------- ^^^^^ the trait `Whatever` is not implemented for `i32`
@@ -153,11 +161,39 @@ help: this trait has no implementations, consider adding one
 LL | trait Whatever {}
    | ^^^^^^^^^^^^^^
 note: required by a bound in `take_whatever`
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:34:26
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:39:26
    |
 LL | fn take_whatever(_: impl Whatever) {}
    |                          ^^^^^^^^ required by this bound in `take_whatever`
 
-error: aborting due to 4 previous errors; 10 warnings emitted
+warning: there is no parameter `DoesNotExist` on trait `Test`
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:31:32
+   |
+LL | #[diagnostic::on_unimplemented(message = "{DoesNotExist}")]
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: expect either a generic argument name or `{Self}` as format argument
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error[E0277]: {DoesNotExist}
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:51:15
+   |
+LL |     take_test(());
+   |     --------- ^^ the trait `Test` is not implemented for `()`
+   |     |
+   |     required by a bound introduced by this call
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:34:1
+   |
+LL | trait Test {}
+   | ^^^^^^^^^^
+note: required by a bound in `take_test`
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:40:22
+   |
+LL | fn take_test(_: impl Test) {}
+   |                      ^^^^ required by this bound in `take_test`
+
+error: aborting due to 5 previous errors; 12 warnings emitted
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/packed/issue-118537-field-offset-ice.rs b/tests/ui/packed/issue-118537-field-offset-ice.rs
new file mode 100644
index 00000000000..657aec64003
--- /dev/null
+++ b/tests/ui/packed/issue-118537-field-offset-ice.rs
@@ -0,0 +1,39 @@
+// run-pass
+#![feature(layout_for_ptr)]
+use std::mem;
+
+#[repr(packed(4))]
+struct Slice([u32]);
+
+#[repr(packed(2), C)]
+struct PackedSized {
+    f: u8,
+    d: [u32; 4],
+}
+
+#[repr(packed(2), C)]
+struct PackedUnsized {
+    f: u8,
+    d: Slice,
+}
+
+impl PackedSized {
+    fn unsize(&self) -> &PackedUnsized {
+        // We can't unsize via a generic type since then we get the error
+        // that packed structs with unsized tail don't work if the tail
+        // might need dropping.
+        let len = 4usize;
+        unsafe { mem::transmute((self, len)) }
+    }
+}
+
+fn main() { unsafe {
+    let p = PackedSized { f: 0, d: [1, 2, 3, 4] };
+    let p = p.unsize() as *const PackedUnsized;
+    // Make sure the size computation correctly adds exact 1 byte of padding
+    // in front of the `d` field.
+    assert_eq!(mem::size_of_val_raw(p), 1 + 1 + 4*4);
+    // And likewise for the offset computation.
+    let d = std::ptr::addr_of!((*p).d);
+    assert_eq!(d.cast::<u32>().read_unaligned(), 1);
+} }
diff --git a/tests/ui/packed/issue-118537-field-offset.rs b/tests/ui/packed/issue-118537-field-offset.rs
new file mode 100644
index 00000000000..cd17f767947
--- /dev/null
+++ b/tests/ui/packed/issue-118537-field-offset.rs
@@ -0,0 +1,36 @@
+// run-pass
+#![feature(layout_for_ptr)]
+use std::mem;
+
+#[repr(packed, C)]
+struct PackedSized {
+    f: u8,
+    d: [u32; 4],
+}
+
+#[repr(packed, C)]
+struct PackedUnsized {
+    f: u8,
+    d: [u32],
+}
+
+impl PackedSized {
+    fn unsize(&self) -> &PackedUnsized {
+        // We can't unsize via a generic type since then we get the error
+        // that packed structs with unsized tail don't work if the tail
+        // might need dropping.
+        let len = 4usize;
+        unsafe { mem::transmute((self, len)) }
+    }
+}
+
+fn main() { unsafe {
+    let p = PackedSized { f: 0, d: [1, 2, 3, 4] };
+    let p = p.unsize() as *const PackedUnsized;
+    // Make sure the size computation does *not* think there is
+    // any padding in front of the `d` field.
+    assert_eq!(mem::size_of_val_raw(p), 1 + 4*4);
+    // And likewise for the offset computation.
+    let d = std::ptr::addr_of!((*p).d);
+    assert_eq!(d.cast::<u32>().read_unaligned(), 1);
+} }