From a33b2f9ad22fc33f90accd7bfa7a07e557b7b271 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Mon, 24 Aug 2026 13:02:57 +0000 Subject: [PATCH 1/8] take `&Item` instead of `Annotatable` as derive macro input --- .../src/deriving/bounds.rs | 4 +- .../src/deriving/clone.rs | 51 ++++----- .../src/deriving/cmp/eq.rs | 2 +- .../src/deriving/cmp/ord.rs | 2 +- .../src/deriving/cmp/partial_eq.rs | 2 +- .../src/deriving/cmp/partial_ord.rs | 49 ++++----- .../src/deriving/coerce_pointee.rs | 10 +- .../src/deriving/debug.rs | 2 +- .../src/deriving/default.rs | 12 +- .../rustc_builtin_macros/src/deriving/from.rs | 8 +- .../src/deriving/generic/mod.rs | 103 ++++++++---------- .../rustc_builtin_macros/src/deriving/hash.rs | 2 +- .../rustc_builtin_macros/src/deriving/mod.rs | 9 +- .../src/deriving/reborrow.rs | 39 +++---- 14 files changed, 130 insertions(+), 165 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/deriving/bounds.rs b/compiler/rustc_builtin_macros/src/deriving/bounds.rs index 48fdb4dd39ce2..5b71d38c63e2e 100644 --- a/compiler/rustc_builtin_macros/src/deriving/bounds.rs +++ b/compiler/rustc_builtin_macros/src/deriving/bounds.rs @@ -9,7 +9,7 @@ pub(crate) fn expand_deriving_copy( cx: &ExtCtxt<'_>, span: Span, mitem: &MetaItem, - item: &Annotatable, + item: &ast::Item, push: &mut dyn FnMut(Annotatable), is_const: bool, ) { @@ -34,7 +34,7 @@ pub(crate) fn expand_deriving_const_param_ty( cx: &ExtCtxt<'_>, span: Span, mitem: &MetaItem, - item: &Annotatable, + item: &ast::Item, push: &mut dyn FnMut(Annotatable), is_const: bool, ) { diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs index b4374e32f6051..be70cf0b584a1 100644 --- a/compiler/rustc_builtin_macros/src/deriving/clone.rs +++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs @@ -12,7 +12,7 @@ pub(crate) fn expand_deriving_clone( cx: &ExtCtxt<'_>, span: Span, mitem: &MetaItem, - item: &Annotatable, + item: &ast::Item, push: &mut dyn FnMut(Annotatable), is_const: bool, ) { @@ -32,35 +32,30 @@ pub(crate) fn expand_deriving_clone( let bounds; let substructure; let is_simple; - match item { - Annotatable::Item(annitem) => match &annitem.kind { - ItemKind::Struct(_, Generics { params, .. }, _) - | ItemKind::Enum(_, Generics { params, .. }, _) => { - let container_id = cx.current_expansion.id.expn_data().parent.expect_local(); - let has_derive_copy = cx.resolver.has_derive_copy(container_id); - bounds = smallvec![]; - if has_derive_copy - && !params - .iter() - .any(|param| matches!(param.kind, ast::GenericParamKind::Type { .. })) - { - is_simple = true; - substructure = - combine_substructure(|c, s, sub| cs_clone_simple(c, s, sub, false)); - } else { - is_simple = false; - substructure = combine_substructure(cs_clone); - } - } - ItemKind::Union(..) => { - bounds = smallvec![Path(path_std!(marker::Copy))]; + match &item.kind { + ItemKind::Struct(_, Generics { params, .. }, _) + | ItemKind::Enum(_, Generics { params, .. }, _) => { + let container_id = cx.current_expansion.id.expn_data().parent.expect_local(); + let has_derive_copy = cx.resolver.has_derive_copy(container_id); + bounds = smallvec![]; + if has_derive_copy + && !params + .iter() + .any(|param| matches!(param.kind, ast::GenericParamKind::Type { .. })) + { is_simple = true; - substructure = combine_substructure(|c, s, sub| cs_clone_simple(c, s, sub, true)); + substructure = combine_substructure(|c, s, sub| cs_clone_simple(c, s, sub, false)); + } else { + is_simple = false; + substructure = combine_substructure(cs_clone); } - _ => cx.dcx().span_bug(span, "`#[derive(Clone)]` on wrong item kind"), - }, - - _ => cx.dcx().span_bug(span, "`#[derive(Clone)]` on trait item or impl item"), + } + ItemKind::Union(..) => { + bounds = smallvec![Path(path_std!(marker::Copy))]; + is_simple = true; + substructure = combine_substructure(|c, s, sub| cs_clone_simple(c, s, sub, true)); + } + _ => cx.dcx().span_bug(span, "`#[derive(Clone)]` on wrong item kind"), } // If the clone method is just copying the value, also mark the type as diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs index 440360ca85d7d..0df5767e2bde0 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs @@ -12,7 +12,7 @@ pub(crate) fn expand_deriving_eq( cx: &ExtCtxt<'_>, span: Span, mitem: &MetaItem, - item: &Annotatable, + item: &ast::Item, push: &mut dyn FnMut(Annotatable), is_const: bool, ) { diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs index a1b38ceadb228..84e5485020a1f 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs @@ -11,7 +11,7 @@ pub(crate) fn expand_deriving_ord( cx: &ExtCtxt<'_>, span: Span, mitem: &MetaItem, - item: &Annotatable, + item: &ast::Item, push: &mut dyn FnMut(Annotatable), is_const: bool, ) { diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs index b852e29b03ca4..fb3d6e9b338f7 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs @@ -13,7 +13,7 @@ pub(crate) fn expand_deriving_partial_eq( cx: &ExtCtxt<'_>, span: Span, mitem: &MetaItem, - item: &Annotatable, + item: &ast::Item, push: &mut dyn FnMut(Annotatable), is_const: bool, ) { diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs index 88141224fddc2..8b778a014ade0 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs @@ -11,7 +11,7 @@ pub(crate) fn expand_deriving_partial_ord( cx: &ExtCtxt<'_>, span: Span, mitem: &MetaItem, - item: &Annotatable, + item: &ast::Item, push: &mut dyn FnMut(Annotatable), is_const: bool, ) { @@ -20,9 +20,7 @@ pub(crate) fn expand_deriving_partial_ord( Path(Path::new_(pathvec!(option::Option), vec![Box::new(ordering_ty)], PathKind::Std)); // Order in which to perform matching - let discr_then_data = if let Annotatable::Item(item) = item - && let ItemKind::Enum(_, _, def) = &item.kind - { + let discr_then_data = if let ItemKind::Enum(_, _, def) = &item.kind { let dataful: Vec = def.variants.iter().map(|v| !v.data.fields().is_empty()).collect(); match dataful.iter().filter(|&&b| b).count() { // No data, placing the discriminant check first makes codegen simpler @@ -49,29 +47,26 @@ pub(crate) fn expand_deriving_partial_ord( let simple_substructure = combine_substructure(|cx, span, _| { cs_partial_cmp_simple(cx, span, cx.expr_ident(span, Ident::new(sym::other, span))) }); - let is_simple = match item { - Annotatable::Item(annitem) => match &annitem.kind { - // For unit structs/zero-variant enums, the default generated code is better. - ItemKind::Struct(.., ast::VariantData::Unit(..)) => false, - // Also for single fieldless variant enum - ItemKind::Enum(.., enum_def) if enum_def.variants.is_empty() => false, - ItemKind::Enum(.., enum_def) - if enum_def.variants.len() == 1 - && matches!(enum_def.variants[0].data, ast::VariantData::Unit(..)) => - { - false - } - ItemKind::Struct(_, ast::Generics { params, .. }, _) - | ItemKind::Enum(_, ast::Generics { params, .. }, _) - if has_derive_ord - && !params - .iter() - .any(|param| matches!(param.kind, ast::GenericParamKind::Type { .. })) => - { - true - } - _ => false, - }, + let is_simple = match &item.kind { + // For unit structs/zero-variant enums, the default generated code is better. + ItemKind::Struct(.., ast::VariantData::Unit(..)) => false, + // Also for single fieldless variant enum + ItemKind::Enum(.., enum_def) if enum_def.variants.is_empty() => false, + ItemKind::Enum(.., enum_def) + if enum_def.variants.len() == 1 + && matches!(enum_def.variants[0].data, ast::VariantData::Unit(..)) => + { + false + } + ItemKind::Struct(_, ast::Generics { params, .. }, _) + | ItemKind::Enum(_, ast::Generics { params, .. }, _) + if has_derive_ord + && !params + .iter() + .any(|param| matches!(param.kind, ast::GenericParamKind::Type { .. })) => + { + true + } _ => false, }; diff --git a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs index 80296a43ee490..a18af8e035c68 100644 --- a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs +++ b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs @@ -1,6 +1,6 @@ use ast::HasAttrs; use rustc_ast::mut_visit::MutVisitor; -use rustc_ast::visit::BoundKind; +use rustc_ast::visit::{BoundKind, Visitor}; use rustc_ast::{ self as ast, GenericArg, GenericBound, GenericParamKind, Generics, ItemKind, MetaItem, TraitBoundModifiers, VariantData, WherePredicate, @@ -22,15 +22,13 @@ pub(crate) fn expand_deriving_coerce_pointee( cx: &ExtCtxt<'_>, span: Span, _mitem: &MetaItem, - item: &Annotatable, + item: &ast::Item, push: &mut dyn FnMut(Annotatable), _is_const: bool, ) { - item.visit_with(&mut DetectNonGenericPointeeAttr { cx }); + DetectNonGenericPointeeAttr { cx }.visit_item(item); - let (name_ident, generics) = if let Annotatable::Item(aitem) = item - && let ItemKind::Struct(ident, g, struct_data) = &aitem.kind - { + let (name_ident, generics) = if let ItemKind::Struct(ident, g, struct_data) = &item.kind { if !matches!( struct_data, VariantData::Struct { fields, recovered: _ } | VariantData::Tuple(fields, _) diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs index c09ac52e74820..0b2fed5ce4947 100644 --- a/compiler/rustc_builtin_macros/src/deriving/debug.rs +++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs @@ -12,7 +12,7 @@ pub(crate) fn expand_deriving_debug( cx: &ExtCtxt<'_>, span: Span, mitem: &MetaItem, - item: &Annotatable, + item: &ast::Item, push: &mut dyn FnMut(Annotatable), is_const: bool, ) { diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs index 3e4c5f1dcfa53..4293c89d15f96 100644 --- a/compiler/rustc_builtin_macros/src/deriving/default.rs +++ b/compiler/rustc_builtin_macros/src/deriving/default.rs @@ -1,6 +1,6 @@ use core::ops::ControlFlow; -use rustc_ast::visit::visit_opt; +use rustc_ast::visit::{Visitor, visit_opt}; use rustc_ast::{self as ast, EnumDef, Safety, VariantData, attr}; use rustc_expand::base::{Annotatable, DummyResult, ExtCtxt}; use rustc_span::{ErrorGuaranteed, Ident, Span, kw, sym}; @@ -15,11 +15,11 @@ pub(crate) fn expand_deriving_default( cx: &ExtCtxt<'_>, span: Span, mitem: &ast::MetaItem, - item: &Annotatable, + item: &ast::Item, push: &mut dyn FnMut(Annotatable), is_const: bool, ) { - item.visit_with(&mut DetectNonVariantDefaultAttr { cx }); + DetectNonVariantDefaultAttr { cx }.visit_item(item); let trait_def = TraitDef { span, @@ -42,7 +42,7 @@ pub(crate) fn expand_deriving_default( default_struct_substructure(cx, trait_span, substr, fields) } StaticEnum(enum_def) => { - default_enum_substructure(cx, trait_span, enum_def, item.span()) + default_enum_substructure(cx, trait_span, enum_def, item.span) } _ => cx.dcx().span_bug(trait_span, "method in `derive(Default)`"), } @@ -308,7 +308,7 @@ impl<'a, 'b> rustc_ast::visit::Visitor<'a> for DetectNonVariantDefaultAttr<'a, ' } } -fn has_a_default_variant(item: &Annotatable) -> bool { +fn has_a_default_variant(item: &ast::Item) -> bool { struct HasDefaultAttrOnVariant; impl<'ast> rustc_ast::visit::Visitor<'ast> for HasDefaultAttrOnVariant { @@ -323,5 +323,5 @@ fn has_a_default_variant(item: &Annotatable) -> bool { } } - item.visit_with(&mut HasDefaultAttrOnVariant).is_break() + HasDefaultAttrOnVariant.visit_item(item).is_break() } diff --git a/compiler/rustc_builtin_macros/src/deriving/from.rs b/compiler/rustc_builtin_macros/src/deriving/from.rs index 9824ab5a225b7..4f7d7fe15b616 100644 --- a/compiler/rustc_builtin_macros/src/deriving/from.rs +++ b/compiler/rustc_builtin_macros/src/deriving/from.rs @@ -16,14 +16,10 @@ pub(crate) fn expand_deriving_from( cx: &ExtCtxt<'_>, span: Span, mitem: &ast::MetaItem, - annotatable: &Annotatable, + item: &ast::Item, push: &mut dyn FnMut(Annotatable), is_const: bool, ) { - let Annotatable::Item(item) = &annotatable else { - cx.dcx().bug("derive(From) used on something else than an item"); - }; - let err_span = || { let item_span = item.kind.ident().map(|ident| ident.span).unwrap_or(item.span); MultiSpan::from_spans(vec![span, item_span]) @@ -127,5 +123,5 @@ pub(crate) fn expand_deriving_from( document: true, }; - from_trait_def.expand(cx, mitem, annotatable, push); + from_trait_def.expand(cx, mitem, item, push); } diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 6a53dafd396df..cfd336fafc4a9 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -179,10 +179,11 @@ use std::{iter, vec}; pub(crate) use StaticFields::*; pub(crate) use SubstructureFields::*; +pub(crate) use rustc_ast as ast; use rustc_ast::token::{IdentIsRaw, LitKind, Token, TokenKind}; use rustc_ast::tokenstream::{DelimSpan, Spacing, TokenTree}; use rustc_ast::{ - self as ast, AnonConst, AttrArgs, BindingMode, ByRef, DelimArgs, EnumDef, Expr, GenericArg, + AnonConst, AttrArgs, BindingMode, ByRef, DelimArgs, EnumDef, Expr, GenericArg, GenericParamKind, Generics, Mutability, PatKind, Safety, SelfKind, VariantData, }; use rustc_attr_ir::{Attribute, AttributeKind, ReprPacked}; @@ -473,7 +474,7 @@ impl<'a> TraitDef<'a> { self, cx: &ExtCtxt<'_>, mitem: &ast::MetaItem, - item: &'a Annotatable, + item: &'a ast::Item, push: &mut dyn FnMut(Annotatable), ) { self.expand_ext(cx, mitem, item, push, false); @@ -483,72 +484,62 @@ impl<'a> TraitDef<'a> { self, cx: &ExtCtxt<'_>, mitem: &ast::MetaItem, - item: &'a Annotatable, + item: &'a ast::Item, push: &mut dyn FnMut(Annotatable), from_scratch: bool, ) { - match item { - Annotatable::Item(item) => { - let is_packed = matches!( - AttributeParser::parse_limited_sym(cx.sess, &item.attrs, &[sym::repr]), - Some(Attribute::Parsed(AttributeKind::Repr { reprs, .. })) if reprs.iter().any(|(x, _)| matches!(x, ReprPacked(..))) - ); + let is_packed = matches!( + AttributeParser::parse_limited_sym(cx.sess, &item.attrs, &[sym::repr]), + Some(Attribute::Parsed(AttributeKind::Repr { reprs, .. })) if reprs.iter().any(|(x, _)| matches!(x, ReprPacked(..))) + ); - let mut newitem = match &item.kind { - ast::ItemKind::Struct(ident, generics, struct_def) => self.expand_struct_def( + let mut newitem = match &item.kind { + ast::ItemKind::Struct(ident, generics, struct_def) => { + self.expand_struct_def(cx, struct_def, *ident, generics, from_scratch, is_packed) + } + ast::ItemKind::Enum(ident, generics, enum_def) => { + // We ignore `is_packed` here, because `repr(packed)` + // enums cause an error later on. + // + // This can only cause further compilation errors + // downstream in blatantly illegal code, so it is fine. + self.expand_enum_def(cx, enum_def, *ident, generics, from_scratch) + } + ast::ItemKind::Union(ident, generics, struct_def) => { + if self.supports_unions { + self.expand_struct_def( cx, struct_def, *ident, generics, from_scratch, is_packed, - ), - ast::ItemKind::Enum(ident, generics, enum_def) => { - // We ignore `is_packed` here, because `repr(packed)` - // enums cause an error later on. - // - // This can only cause further compilation errors - // downstream in blatantly illegal code, so it is fine. - self.expand_enum_def(cx, enum_def, *ident, generics, from_scratch) - } - ast::ItemKind::Union(ident, generics, struct_def) => { - if self.supports_unions { - self.expand_struct_def( - cx, - struct_def, - *ident, - generics, - from_scratch, - is_packed, - ) - } else { - cx.dcx().emit_err(diagnostics::DeriveUnion { span: mitem.span }); - return; - } - } - _ => unreachable!(), - }; - // Keep the lint attributes of the previous item to control how the - // generated implementations are linted - newitem.attrs.extend( - item.attrs - .iter() - .filter(|a| { - a.has_any_name(&[ - sym::allow, - sym::warn, - sym::deny, - sym::forbid, - sym::stable, - sym::unstable, - ]) - }) - .cloned(), - ); - push(Annotatable::Item(newitem)) + ) + } else { + cx.dcx().emit_err(diagnostics::DeriveUnion { span: mitem.span }); + return; + } } _ => unreachable!(), - } + }; + // Keep the lint attributes of the previous item to control how the + // generated implementations are linted + newitem.attrs.extend( + item.attrs + .iter() + .filter(|a| { + a.has_any_name(&[ + sym::allow, + sym::warn, + sym::deny, + sym::forbid, + sym::stable, + sym::unstable, + ]) + }) + .cloned(), + ); + push(Annotatable::Item(newitem)) } /// Given that we are deriving a trait `DerivedTrait` for a type like: diff --git a/compiler/rustc_builtin_macros/src/deriving/hash.rs b/compiler/rustc_builtin_macros/src/deriving/hash.rs index f1931aa90a435..5e32a12b6fdca 100644 --- a/compiler/rustc_builtin_macros/src/deriving/hash.rs +++ b/compiler/rustc_builtin_macros/src/deriving/hash.rs @@ -11,7 +11,7 @@ pub(crate) fn expand_deriving_hash( cx: &ExtCtxt<'_>, span: Span, mitem: &MetaItem, - item: &Annotatable, + item: &ast::Item, push: &mut dyn FnMut(Annotatable), is_const: bool, ) { diff --git a/compiler/rustc_builtin_macros/src/deriving/mod.rs b/compiler/rustc_builtin_macros/src/deriving/mod.rs index 602af919bd4f2..55838e09b304b 100644 --- a/compiler/rustc_builtin_macros/src/deriving/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/mod.rs @@ -35,7 +35,7 @@ pub(crate) mod partial_ord; pub(crate) mod generic; pub(crate) type BuiltinDeriveFn = - fn(&ExtCtxt<'_>, Span, &MetaItem, &Annotatable, &mut dyn FnMut(Annotatable), bool); + fn(&ExtCtxt<'_>, Span, &MetaItem, &ast::Item, &mut dyn FnMut(Annotatable), bool); pub(crate) struct BuiltinDerive(pub(crate) BuiltinDeriveFn); @@ -59,7 +59,7 @@ impl MultiItemModifier for BuiltinDerive { ecx, span, meta_item, - &Annotatable::Item(item), + &item, &mut |a| { // Cannot use 'ecx.stmt_item' here, because we need to pass 'ecx' // to the function @@ -75,9 +75,10 @@ impl MultiItemModifier for BuiltinDerive { unreachable!("should have already errored on non-item statement") } } - _ => { - (self.0)(ecx, span, meta_item, &item, &mut |a| items.push(a), is_derive_const); + Annotatable::Item(item) => { + (self.0)(ecx, span, meta_item, &item, &mut |a| items.push(a), is_derive_const) } + _ => unreachable!(), } ExpandResult::Ready(items) } diff --git a/compiler/rustc_builtin_macros/src/deriving/reborrow.rs b/compiler/rustc_builtin_macros/src/deriving/reborrow.rs index 9dc1ccf4fd8e6..c1b8dfb53c694 100644 --- a/compiler/rustc_builtin_macros/src/deriving/reborrow.rs +++ b/compiler/rustc_builtin_macros/src/deriving/reborrow.rs @@ -15,7 +15,7 @@ pub(crate) fn expand_deriving_reborrow( cx: &ExtCtxt<'_>, span: Span, _mitem: &MetaItem, - item: &Annotatable, + item: &ast::Item, push: &mut dyn FnMut(Annotatable), _is_const: bool, ) { @@ -30,7 +30,7 @@ pub(crate) fn expand_deriving_coerce_shared( cx: &ExtCtxt<'_>, span: Span, _mitem: &MetaItem, - item: &Annotatable, + item: &ast::Item, push: &mut dyn FnMut(Annotatable), _is_const: bool, ) { @@ -55,25 +55,19 @@ pub(crate) fn expand_deriving_coerce_shared( fn struct_def<'a>( cx: &ExtCtxt<'_>, span: Span, - item: &'a Annotatable, + item: &'a ast::Item, trait_name: Symbol, ) -> Option<(Ident, &'a Generics)> { - match item { - Annotatable::Item(item) => match &item.kind { - ItemKind::Struct(ident, generics, _) => Some((*ident, generics)), - ItemKind::Enum(..) => { - cx.dcx().emit_err(UnsupportedItem { span, trait_name, kind: "enum" }); - None - } - ItemKind::Union(..) => { - cx.dcx().emit_err(UnsupportedItem { span, trait_name, kind: "union" }); - None - } - _ => { - cx.dcx().emit_err(UnsupportedItem { span, trait_name, kind: "item" }); - None - } - }, + match &item.kind { + ItemKind::Struct(ident, generics, _) => Some((*ident, generics)), + ItemKind::Enum(..) => { + cx.dcx().emit_err(UnsupportedItem { span, trait_name, kind: "enum" }); + None + } + ItemKind::Union(..) => { + cx.dcx().emit_err(UnsupportedItem { span, trait_name, kind: "union" }); + None + } _ => { cx.dcx().emit_err(UnsupportedItem { span, trait_name, kind: "item" }); None @@ -81,12 +75,7 @@ fn struct_def<'a>( } } -fn coerce_shared_target(cx: &ExtCtxt<'_>, span: Span, item: &Annotatable) -> Option> { - let Annotatable::Item(item) = item else { - cx.dcx().emit_err(MissingTarget { span }); - return None; - }; - +fn coerce_shared_target(cx: &ExtCtxt<'_>, span: Span, item: &ast::Item) -> Option> { let mut attrs = item.attrs.iter().filter(|attr| attr.has_name(sym::coerce_shared)); let Some(attr) = attrs.next() else { cx.dcx().emit_err(MissingTarget { span }); From 04b8e09c9859f30a9a39858c17e3171bbe7c4775 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Mon, 24 Aug 2026 13:11:46 +0000 Subject: [PATCH 2/8] take `Box` instead of `Annotatable` as the `push` argument --- .../rustc_builtin_macros/src/deriving/bounds.rs | 6 +++--- .../rustc_builtin_macros/src/deriving/clone.rs | 4 ++-- .../rustc_builtin_macros/src/deriving/cmp/eq.rs | 4 ++-- .../rustc_builtin_macros/src/deriving/cmp/ord.rs | 4 ++-- .../src/deriving/cmp/partial_eq.rs | 4 ++-- .../src/deriving/cmp/partial_ord.rs | 4 ++-- .../src/deriving/coerce_pointee.rs | 10 +++++----- .../rustc_builtin_macros/src/deriving/debug.rs | 4 ++-- .../rustc_builtin_macros/src/deriving/default.rs | 4 ++-- .../rustc_builtin_macros/src/deriving/from.rs | 4 ++-- .../src/deriving/generic/mod.rs | 8 ++++---- .../rustc_builtin_macros/src/deriving/hash.rs | 4 ++-- compiler/rustc_builtin_macros/src/deriving/mod.rs | 15 ++++++++++----- .../rustc_builtin_macros/src/deriving/reborrow.rs | 12 ++++++------ 14 files changed, 46 insertions(+), 41 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/deriving/bounds.rs b/compiler/rustc_builtin_macros/src/deriving/bounds.rs index 5b71d38c63e2e..da5370e3e7819 100644 --- a/compiler/rustc_builtin_macros/src/deriving/bounds.rs +++ b/compiler/rustc_builtin_macros/src/deriving/bounds.rs @@ -1,5 +1,5 @@ use rustc_ast::{MetaItem, Safety}; -use rustc_expand::base::{Annotatable, ExtCtxt}; +use rustc_expand::base::ExtCtxt; use rustc_span::Span; use crate::deriving::generic::*; @@ -10,7 +10,7 @@ pub(crate) fn expand_deriving_copy( span: Span, mitem: &MetaItem, item: &ast::Item, - push: &mut dyn FnMut(Annotatable), + push: &mut dyn FnMut(Box), is_const: bool, ) { let trait_def = TraitDef { @@ -35,7 +35,7 @@ pub(crate) fn expand_deriving_const_param_ty( span: Span, mitem: &MetaItem, item: &ast::Item, - push: &mut dyn FnMut(Annotatable), + push: &mut dyn FnMut(Box), is_const: bool, ) { let trait_def = TraitDef { diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs index be70cf0b584a1..f0c274bce5b58 100644 --- a/compiler/rustc_builtin_macros/src/deriving/clone.rs +++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs @@ -1,6 +1,6 @@ use rustc_ast::{self as ast, Generics, ItemKind, MetaItem, Safety, VariantData}; use rustc_data_structures::fx::FxHashSet; -use rustc_expand::base::{Annotatable, ExtCtxt}; +use rustc_expand::base::ExtCtxt; use rustc_span::{DUMMY_SP, Ident, Span, kw, sym}; use thin_vec::{ThinVec, thin_vec}; @@ -13,7 +13,7 @@ pub(crate) fn expand_deriving_clone( span: Span, mitem: &MetaItem, item: &ast::Item, - push: &mut dyn FnMut(Annotatable), + push: &mut dyn FnMut(Box), is_const: bool, ) { // The simple form is `fn clone(&self) -> Self { *self }`, possibly with diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs index 0df5767e2bde0..8c160cb9868bf 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs @@ -1,6 +1,6 @@ use rustc_ast::{self as ast, MetaItem, Safety}; use rustc_data_structures::fx::FxHashSet; -use rustc_expand::base::{Annotatable, ExtCtxt}; +use rustc_expand::base::ExtCtxt; use rustc_span::{Span, sym}; use thin_vec::{ThinVec, thin_vec}; @@ -13,7 +13,7 @@ pub(crate) fn expand_deriving_eq( span: Span, mitem: &MetaItem, item: &ast::Item, - push: &mut dyn FnMut(Annotatable), + push: &mut dyn FnMut(Box), is_const: bool, ) { let span = cx.with_def_site_ctxt(span); diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs index 84e5485020a1f..fb8d425841722 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs @@ -1,5 +1,5 @@ use rustc_ast::{MetaItem, Safety}; -use rustc_expand::base::{Annotatable, ExtCtxt}; +use rustc_expand::base::ExtCtxt; use rustc_span::{Ident, Span, sym}; use thin_vec::thin_vec; @@ -12,7 +12,7 @@ pub(crate) fn expand_deriving_ord( span: Span, mitem: &MetaItem, item: &ast::Item, - push: &mut dyn FnMut(Annotatable), + push: &mut dyn FnMut(Box), is_const: bool, ) { let trait_def = TraitDef { diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs index fb3d6e9b338f7..8c442f7dbaa5f 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs @@ -1,5 +1,5 @@ use rustc_ast::{BinOpKind, BorrowKind, Expr, ExprKind, MetaItem, Mutability, Safety}; -use rustc_expand::base::{Annotatable, ExtCtxt}; +use rustc_expand::base::ExtCtxt; use rustc_span::{Span, sym}; use thin_vec::thin_vec; @@ -14,7 +14,7 @@ pub(crate) fn expand_deriving_partial_eq( span: Span, mitem: &MetaItem, item: &ast::Item, - push: &mut dyn FnMut(Annotatable), + push: &mut dyn FnMut(Box), is_const: bool, ) { let structural_trait_def = TraitDef { diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs index 8b778a014ade0..0e547d441a74b 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs @@ -1,5 +1,5 @@ use rustc_ast::{ExprKind, ItemKind, MetaItem, PatKind, Safety, ast}; -use rustc_expand::base::{Annotatable, ExtCtxt}; +use rustc_expand::base::ExtCtxt; use rustc_span::{Ident, Span, sym}; use thin_vec::thin_vec; @@ -12,7 +12,7 @@ pub(crate) fn expand_deriving_partial_ord( span: Span, mitem: &MetaItem, item: &ast::Item, - push: &mut dyn FnMut(Annotatable), + push: &mut dyn FnMut(Box), is_const: bool, ) { let ordering_ty = Path(path_std!(cmp::Ordering)); diff --git a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs index a18af8e035c68..58b4734b132c3 100644 --- a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs +++ b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs @@ -7,7 +7,7 @@ use rustc_ast::{ }; use rustc_data_structures::flat_map_in_place::FlatMapInPlace; use rustc_errors::E0802; -use rustc_expand::base::{Annotatable, ExtCtxt}; +use rustc_expand::base::ExtCtxt; use rustc_macros::Diagnostic; use rustc_span::{Ident, Span, Symbol, sym}; use thin_vec::{ThinVec, thin_vec}; @@ -23,7 +23,7 @@ pub(crate) fn expand_deriving_coerce_pointee( span: Span, _mitem: &MetaItem, item: &ast::Item, - push: &mut dyn FnMut(Annotatable), + push: &mut dyn FnMut(Box), _is_const: bool, ) { DetectNonGenericPointeeAttr { cx }.visit_item(item); @@ -102,7 +102,7 @@ pub(crate) fn expand_deriving_coerce_pointee( let trait_path = cx.path_all(span, true, path!(span, core::marker::CoercePointeeValidated), vec![]); let trait_ref = cx.trait_ref(trait_path); - push(Annotatable::Item( + push( cx.item( span, attrs.clone(), @@ -142,7 +142,7 @@ pub(crate) fn expand_deriving_coerce_pointee( items: ThinVec::new(), }), ), - )); + ); } let mut add_impl_block = |generics, trait_symbol, trait_args| { let mut parts = path!(span, core::ops); @@ -165,7 +165,7 @@ pub(crate) fn expand_deriving_coerce_pointee( items: ThinVec::new(), }), ); - push(Annotatable::Item(item)); + push(item); }; // Create unsized `self`, that is, one where the `#[pointee]` type arg is replaced with `__S`. For diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs index 0b2fed5ce4947..f31dfe65d01ed 100644 --- a/compiler/rustc_builtin_macros/src/deriving/debug.rs +++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs @@ -1,5 +1,5 @@ use rustc_ast::{self as ast, EnumDef, ExprKind, MetaItem, Safety, TyKind, token}; -use rustc_expand::base::{Annotatable, ExtCtxt}; +use rustc_expand::base::ExtCtxt; use rustc_session::config::FmtDebug; use rustc_span::{Ident, Span, Symbol, sym}; use thin_vec::{ThinVec, thin_vec}; @@ -13,7 +13,7 @@ pub(crate) fn expand_deriving_debug( span: Span, mitem: &MetaItem, item: &ast::Item, - push: &mut dyn FnMut(Annotatable), + push: &mut dyn FnMut(Box), is_const: bool, ) { // &mut ::std::fmt::Formatter diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs index 4293c89d15f96..88e9d8daf1bd9 100644 --- a/compiler/rustc_builtin_macros/src/deriving/default.rs +++ b/compiler/rustc_builtin_macros/src/deriving/default.rs @@ -2,7 +2,7 @@ use core::ops::ControlFlow; use rustc_ast::visit::{Visitor, visit_opt}; use rustc_ast::{self as ast, EnumDef, Safety, VariantData, attr}; -use rustc_expand::base::{Annotatable, DummyResult, ExtCtxt}; +use rustc_expand::base::{DummyResult, ExtCtxt}; use rustc_span::{ErrorGuaranteed, Ident, Span, kw, sym}; use smallvec::SmallVec; use thin_vec::{ThinVec, thin_vec}; @@ -16,7 +16,7 @@ pub(crate) fn expand_deriving_default( span: Span, mitem: &ast::MetaItem, item: &ast::Item, - push: &mut dyn FnMut(Annotatable), + push: &mut dyn FnMut(Box), is_const: bool, ) { DetectNonVariantDefaultAttr { cx }.visit_item(item); diff --git a/compiler/rustc_builtin_macros/src/deriving/from.rs b/compiler/rustc_builtin_macros/src/deriving/from.rs index 4f7d7fe15b616..ab5008f90ff00 100644 --- a/compiler/rustc_builtin_macros/src/deriving/from.rs +++ b/compiler/rustc_builtin_macros/src/deriving/from.rs @@ -1,7 +1,7 @@ use rustc_ast as ast; use rustc_ast::{ItemKind, Safety, VariantData}; use rustc_errors::MultiSpan; -use rustc_expand::base::{Annotatable, DummyResult, ExtCtxt}; +use rustc_expand::base::{DummyResult, ExtCtxt}; use rustc_span::{Ident, Span, kw, sym}; use thin_vec::thin_vec; @@ -17,7 +17,7 @@ pub(crate) fn expand_deriving_from( span: Span, mitem: &ast::MetaItem, item: &ast::Item, - push: &mut dyn FnMut(Annotatable), + push: &mut dyn FnMut(Box), is_const: bool, ) { let err_span = || { diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index cfd336fafc4a9..436881dbf2209 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -188,7 +188,7 @@ use rustc_ast::{ }; use rustc_attr_ir::{Attribute, AttributeKind, ReprPacked}; use rustc_attr_parsing::AttributeParser; -use rustc_expand::base::{Annotatable, ExtCtxt}; +use rustc_expand::base::ExtCtxt; use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, respan, sym}; pub(crate) use smallvec::{SmallVec, smallvec}; use thin_vec::{ThinVec, thin_vec}; @@ -475,7 +475,7 @@ impl<'a> TraitDef<'a> { cx: &ExtCtxt<'_>, mitem: &ast::MetaItem, item: &'a ast::Item, - push: &mut dyn FnMut(Annotatable), + push: &mut dyn FnMut(Box), ) { self.expand_ext(cx, mitem, item, push, false); } @@ -485,7 +485,7 @@ impl<'a> TraitDef<'a> { cx: &ExtCtxt<'_>, mitem: &ast::MetaItem, item: &'a ast::Item, - push: &mut dyn FnMut(Annotatable), + push: &mut dyn FnMut(Box), from_scratch: bool, ) { let is_packed = matches!( @@ -539,7 +539,7 @@ impl<'a> TraitDef<'a> { }) .cloned(), ); - push(Annotatable::Item(newitem)) + push(newitem); } /// Given that we are deriving a trait `DerivedTrait` for a type like: diff --git a/compiler/rustc_builtin_macros/src/deriving/hash.rs b/compiler/rustc_builtin_macros/src/deriving/hash.rs index 5e32a12b6fdca..6864b05ae08cd 100644 --- a/compiler/rustc_builtin_macros/src/deriving/hash.rs +++ b/compiler/rustc_builtin_macros/src/deriving/hash.rs @@ -1,5 +1,5 @@ use rustc_ast::{MetaItem, Mutability, Safety}; -use rustc_expand::base::{Annotatable, ExtCtxt}; +use rustc_expand::base::ExtCtxt; use rustc_span::{Span, sym}; use thin_vec::thin_vec; @@ -12,7 +12,7 @@ pub(crate) fn expand_deriving_hash( span: Span, mitem: &MetaItem, item: &ast::Item, - push: &mut dyn FnMut(Annotatable), + push: &mut dyn FnMut(Box), is_const: bool, ) { let path = path_std!(hash::Hash); diff --git a/compiler/rustc_builtin_macros/src/deriving/mod.rs b/compiler/rustc_builtin_macros/src/deriving/mod.rs index 55838e09b304b..7c010f62bfd15 100644 --- a/compiler/rustc_builtin_macros/src/deriving/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/mod.rs @@ -35,7 +35,7 @@ pub(crate) mod partial_ord; pub(crate) mod generic; pub(crate) type BuiltinDeriveFn = - fn(&ExtCtxt<'_>, Span, &MetaItem, &ast::Item, &mut dyn FnMut(Annotatable), bool); + fn(&ExtCtxt<'_>, Span, &MetaItem, &ast::Item, &mut dyn FnMut(Box), bool); pub(crate) struct BuiltinDerive(pub(crate) BuiltinDeriveFn); @@ -65,7 +65,7 @@ impl MultiItemModifier for BuiltinDerive { // to the function items.push(Annotatable::Stmt(Box::new(ast::Stmt { id: ast::DUMMY_NODE_ID, - kind: ast::StmtKind::Item(a.expect_item()), + kind: ast::StmtKind::Item(a), span, }))); }, @@ -75,9 +75,14 @@ impl MultiItemModifier for BuiltinDerive { unreachable!("should have already errored on non-item statement") } } - Annotatable::Item(item) => { - (self.0)(ecx, span, meta_item, &item, &mut |a| items.push(a), is_derive_const) - } + Annotatable::Item(item) => (self.0)( + ecx, + span, + meta_item, + &item, + &mut |a| items.push(Annotatable::Item(a)), + is_derive_const, + ), _ => unreachable!(), } ExpandResult::Ready(items) diff --git a/compiler/rustc_builtin_macros/src/deriving/reborrow.rs b/compiler/rustc_builtin_macros/src/deriving/reborrow.rs index c1b8dfb53c694..43d24417acc00 100644 --- a/compiler/rustc_builtin_macros/src/deriving/reborrow.rs +++ b/compiler/rustc_builtin_macros/src/deriving/reborrow.rs @@ -2,7 +2,7 @@ use rustc_ast::{ self as ast, AttrArgs, GenericArg, GenericParamKind, Generics, ItemKind, MetaItem, token, }; use rustc_errors::E0802; -use rustc_expand::base::{Annotatable, ExtCtxt}; +use rustc_expand::base::ExtCtxt; use rustc_macros::Diagnostic; use rustc_span::{Ident, Span, Symbol, sym}; use thin_vec::ThinVec; @@ -16,7 +16,7 @@ pub(crate) fn expand_deriving_reborrow( span: Span, _mitem: &MetaItem, item: &ast::Item, - push: &mut dyn FnMut(Annotatable), + push: &mut dyn FnMut(Box), _is_const: bool, ) { let Some((ident, generics)) = struct_def(cx, span, item, sym::Reborrow) else { @@ -31,7 +31,7 @@ pub(crate) fn expand_deriving_coerce_shared( span: Span, _mitem: &MetaItem, item: &ast::Item, - push: &mut dyn FnMut(Annotatable), + push: &mut dyn FnMut(Box), _is_const: bool, ) { let Some((ident, generics)) = struct_def(cx, span, item, sym::CoerceShared) else { @@ -119,7 +119,7 @@ fn push_marker_impl( generics: &Generics, trait_name: Symbol, trait_args: Vec, - push: &mut dyn FnMut(Annotatable), + push: &mut dyn FnMut(Box), ) { let mut trait_parts = path!(span, core::marker); trait_parts.push(Ident::new(trait_name, span)); @@ -143,7 +143,7 @@ fn push_marker_impl( .collect(); let self_ty = cx.ty_path(cx.path_all(span, false, vec![ident], self_params)); - push(Annotatable::Item(cx.item( + push(cx.item( span, thin_vec::thin_vec![cx.attr_word(sym::automatically_derived, span)], ast::ItemKind::Impl(ast::Impl { @@ -158,7 +158,7 @@ fn push_marker_impl( self_ty, items: ThinVec::new(), }), - ))); + )); } fn impl_generics(cx: &ExtCtxt<'_>, generics: &Generics) -> Generics { From 1343cc348e0fd6d16a67f1e6cb5ec16526f19ab1 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Wed, 26 Aug 2026 11:24:54 +0000 Subject: [PATCH 3/8] several small cleanups --- .../src/deriving/cmp/partial_eq.rs | 12 +++++------- compiler/rustc_builtin_macros/src/deriving/from.rs | 2 +- compiler/rustc_builtin_macros/src/deriving/mod.rs | 10 +--------- 3 files changed, 7 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs index 8c442f7dbaa5f..a65962bfc9731 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs @@ -47,9 +47,7 @@ pub(crate) fn expand_deriving_partial_eq( ret_ty: Path(generic::ty::Path::new_local(sym::bool)), attributes: thin_vec![cx.attr_word(sym::inline, span)], fieldless_variants_strategy: FieldlessVariantsStrategy::Unify, - combine_substructure: combine_substructure(|a, b, c| { - BlockOrExpr::new_expr(get_substructure_equality_expr(a, b, c)) - }), + combine_substructure: combine_substructure(get_substructure_equality_expr), }]; let trait_def = TraitDef { @@ -123,10 +121,10 @@ fn get_substructure_equality_expr( cx: &ExtCtxt<'_>, span: Span, substructure: &Substructure<'_>, -) -> Box { +) -> BlockOrExpr { use SubstructureFields::*; - match substructure.fields { + BlockOrExpr::new_expr(match substructure.fields { EnumMatching(.., fields) | Struct(.., fields) => { let combine = move |acc, field| { let rhs = get_field_equality_expr(cx, field); @@ -151,7 +149,7 @@ fn get_substructure_equality_expr( EnumDiscr(disc, match_expr) => { let lhs = get_field_equality_expr(cx, disc); let Some(match_expr) = match_expr else { - return lhs; + return BlockOrExpr::new_expr(lhs); }; // Compare the discriminant first (cheaper), then the rest of the // fields. @@ -169,7 +167,7 @@ fn get_substructure_equality_expr( span, "unexpected all-fieldless enum encountered during `derive(PartialEq)` expansion", ), - } + }) } /// Generates an equality comparison expression for a single struct or enum diff --git a/compiler/rustc_builtin_macros/src/deriving/from.rs b/compiler/rustc_builtin_macros/src/deriving/from.rs index ab5008f90ff00..0758ff0269a96 100644 --- a/compiler/rustc_builtin_macros/src/deriving/from.rs +++ b/compiler/rustc_builtin_macros/src/deriving/from.rs @@ -75,7 +75,7 @@ pub(crate) fn expand_deriving_from( supports_unions: false, methods: smallvec![MethodDef { name: sym::from, - generics: Bounds { bounds: vec![] }, + generics: Bounds::empty(), explicit_self: false, nonself_args: smallvec![(from_type, sym::value)], ret_ty: Ty::Self_, diff --git a/compiler/rustc_builtin_macros/src/deriving/mod.rs b/compiler/rustc_builtin_macros/src/deriving/mod.rs index 7c010f62bfd15..75bd98893de80 100644 --- a/compiler/rustc_builtin_macros/src/deriving/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/mod.rs @@ -60,15 +60,7 @@ impl MultiItemModifier for BuiltinDerive { span, meta_item, &item, - &mut |a| { - // Cannot use 'ecx.stmt_item' here, because we need to pass 'ecx' - // to the function - items.push(Annotatable::Stmt(Box::new(ast::Stmt { - id: ast::DUMMY_NODE_ID, - kind: ast::StmtKind::Item(a), - span, - }))); - }, + &mut |a| items.push(Annotatable::Stmt(Box::new(ecx.stmt_item(span, a)))), is_derive_const, ); } else { From 9cde67f7c862c78d7796cb993fb9fb594fdf211e Mon Sep 17 00:00:00 2001 From: cyrgani Date: Thu, 27 Aug 2026 10:02:57 +0000 Subject: [PATCH 4/8] remove one use of `expand_ext` --- compiler/rustc_builtin_macros/src/deriving/clone.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs index f0c274bce5b58..f072b4b9e5cd1 100644 --- a/compiler/rustc_builtin_macros/src/deriving/clone.rs +++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs @@ -77,7 +77,7 @@ pub(crate) fn expand_deriving_clone( document: false, }; - trivial_def.expand_ext(cx, mitem, item, push, true); + trivial_def.expand(cx, mitem, item, push); } let trait_def = TraitDef { From 898fc7fb85c37c9234eb8826caaf9663fe83a649 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Thu, 27 Aug 2026 11:54:24 +0000 Subject: [PATCH 5/8] dissolve the `cmp` subdirectory --- .../rustc_builtin_macros/src/deriving/{cmp => }/eq.rs | 0 compiler/rustc_builtin_macros/src/deriving/mod.rs | 9 ++------- .../rustc_builtin_macros/src/deriving/{cmp => }/ord.rs | 0 .../src/deriving/{cmp => }/partial_eq.rs | 0 .../src/deriving/{cmp => }/partial_ord.rs | 0 5 files changed, 2 insertions(+), 7 deletions(-) rename compiler/rustc_builtin_macros/src/deriving/{cmp => }/eq.rs (100%) rename compiler/rustc_builtin_macros/src/deriving/{cmp => }/ord.rs (100%) rename compiler/rustc_builtin_macros/src/deriving/{cmp => }/partial_eq.rs (100%) rename compiler/rustc_builtin_macros/src/deriving/{cmp => }/partial_ord.rs (100%) diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs b/compiler/rustc_builtin_macros/src/deriving/eq.rs similarity index 100% rename from compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs rename to compiler/rustc_builtin_macros/src/deriving/eq.rs diff --git a/compiler/rustc_builtin_macros/src/deriving/mod.rs b/compiler/rustc_builtin_macros/src/deriving/mod.rs index 75bd98893de80..337ee43938bd7 100644 --- a/compiler/rustc_builtin_macros/src/deriving/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/mod.rs @@ -19,18 +19,13 @@ pub(crate) mod clone; pub(crate) mod coerce_pointee; pub(crate) mod debug; pub(crate) mod default; +pub(crate) mod eq; pub(crate) mod from; pub(crate) mod hash; -pub(crate) mod reborrow; - -#[path = "cmp/eq.rs"] -pub(crate) mod eq; -#[path = "cmp/ord.rs"] pub(crate) mod ord; -#[path = "cmp/partial_eq.rs"] pub(crate) mod partial_eq; -#[path = "cmp/partial_ord.rs"] pub(crate) mod partial_ord; +pub(crate) mod reborrow; pub(crate) mod generic; diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs b/compiler/rustc_builtin_macros/src/deriving/ord.rs similarity index 100% rename from compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs rename to compiler/rustc_builtin_macros/src/deriving/ord.rs diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs b/compiler/rustc_builtin_macros/src/deriving/partial_eq.rs similarity index 100% rename from compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs rename to compiler/rustc_builtin_macros/src/deriving/partial_eq.rs diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs b/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs similarity index 100% rename from compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs rename to compiler/rustc_builtin_macros/src/deriving/partial_ord.rs From 2e9a42802a20dc96162ff7109af592eff8d05bc4 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Thu, 27 Aug 2026 12:00:20 +0000 Subject: [PATCH 6/8] split `bounds` module into `const_param_ty` and `copy` modules --- .../deriving/{bounds.rs => const_param_ty.rs} | 25 --------------- .../rustc_builtin_macros/src/deriving/copy.rs | 31 +++++++++++++++++++ .../rustc_builtin_macros/src/deriving/mod.rs | 3 +- compiler/rustc_builtin_macros/src/lib.rs | 4 +-- 4 files changed, 35 insertions(+), 28 deletions(-) rename compiler/rustc_builtin_macros/src/deriving/{bounds.rs => const_param_ty.rs} (56%) create mode 100644 compiler/rustc_builtin_macros/src/deriving/copy.rs diff --git a/compiler/rustc_builtin_macros/src/deriving/bounds.rs b/compiler/rustc_builtin_macros/src/deriving/const_param_ty.rs similarity index 56% rename from compiler/rustc_builtin_macros/src/deriving/bounds.rs rename to compiler/rustc_builtin_macros/src/deriving/const_param_ty.rs index da5370e3e7819..18a9df86b547e 100644 --- a/compiler/rustc_builtin_macros/src/deriving/bounds.rs +++ b/compiler/rustc_builtin_macros/src/deriving/const_param_ty.rs @@ -5,31 +5,6 @@ use rustc_span::Span; use crate::deriving::generic::*; use crate::deriving::path_std; -pub(crate) fn expand_deriving_copy( - cx: &ExtCtxt<'_>, - span: Span, - mitem: &MetaItem, - item: &ast::Item, - push: &mut dyn FnMut(Box), - is_const: bool, -) { - let trait_def = TraitDef { - span, - path: path_std!(marker::Copy), - skip_path_as_bound: false, - needs_copy_as_bound_if_packed: false, - additional_bounds: SmallVec::new(), - supports_unions: true, - methods: SmallVec::new(), - associated_types: SmallVec::new(), - is_const, - safety: Safety::Default, - document: true, - }; - - trait_def.expand(cx, mitem, item, push); -} - pub(crate) fn expand_deriving_const_param_ty( cx: &ExtCtxt<'_>, span: Span, diff --git a/compiler/rustc_builtin_macros/src/deriving/copy.rs b/compiler/rustc_builtin_macros/src/deriving/copy.rs new file mode 100644 index 0000000000000..5743d27cf7458 --- /dev/null +++ b/compiler/rustc_builtin_macros/src/deriving/copy.rs @@ -0,0 +1,31 @@ +use rustc_ast::{MetaItem, Safety}; +use rustc_expand::base::ExtCtxt; +use rustc_span::Span; + +use crate::deriving::generic::*; +use crate::deriving::path_std; + +pub(crate) fn expand_deriving_copy( + cx: &ExtCtxt<'_>, + span: Span, + mitem: &MetaItem, + item: &ast::Item, + push: &mut dyn FnMut(Box), + is_const: bool, +) { + let trait_def = TraitDef { + span, + path: path_std!(marker::Copy), + skip_path_as_bound: false, + needs_copy_as_bound_if_packed: false, + additional_bounds: SmallVec::new(), + supports_unions: true, + methods: SmallVec::new(), + associated_types: SmallVec::new(), + is_const, + safety: Safety::Default, + document: true, + }; + + trait_def.expand(cx, mitem, item, push); +} diff --git a/compiler/rustc_builtin_macros/src/deriving/mod.rs b/compiler/rustc_builtin_macros/src/deriving/mod.rs index 337ee43938bd7..404991903c424 100644 --- a/compiler/rustc_builtin_macros/src/deriving/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/mod.rs @@ -14,9 +14,10 @@ macro path_std($($x:tt)*) { generic::ty::Path::new( pathvec!( $($x)* ) ) } -pub(crate) mod bounds; pub(crate) mod clone; pub(crate) mod coerce_pointee; +pub(crate) mod const_param_ty; +pub(crate) mod copy; pub(crate) mod debug; pub(crate) mod default; pub(crate) mod eq; diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index db92413e1b162..57759bb113401 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -133,8 +133,8 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) { register_derive! { Clone: clone::expand_deriving_clone, CoerceShared: reborrow::expand_deriving_coerce_shared, - Copy: bounds::expand_deriving_copy, - ConstParamTy: bounds::expand_deriving_const_param_ty, + Copy: copy::expand_deriving_copy, + ConstParamTy: const_param_ty::expand_deriving_const_param_ty, Debug: debug::expand_deriving_debug, Default: default::expand_deriving_default, Eq: eq::expand_deriving_eq, From e27ac1e5d9e51fa6acda5030c8fb428d2bbf710b Mon Sep 17 00:00:00 2001 From: cyrgani Date: Thu, 27 Aug 2026 12:35:28 +0000 Subject: [PATCH 7/8] remove last `StaticFields` usage --- .../src/deriving/default.rs | 40 +++++++++++-------- tests/ui/derives/deriving-all-codegen.stdout | 2 +- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs index 88e9d8daf1bd9..eb9a302be31e0 100644 --- a/compiler/rustc_builtin_macros/src/deriving/default.rs +++ b/compiler/rustc_builtin_macros/src/deriving/default.rs @@ -38,8 +38,8 @@ pub(crate) fn expand_deriving_default( fieldless_variants_strategy: FieldlessVariantsStrategy::Default, combine_substructure: combine_substructure(|cx, trait_span, substr| { match substr.fields { - StaticStruct(_, fields) => { - default_struct_substructure(cx, trait_span, substr, fields) + StaticStruct(variant_data, _) => { + default_struct_substructure(cx, trait_span, substr, variant_data) } StaticEnum(enum_def) => { default_enum_substructure(cx, trait_span, enum_def, item.span) @@ -66,27 +66,35 @@ fn default_struct_substructure( cx: &ExtCtxt<'_>, trait_span: Span, substr: &Substructure<'_>, - summary: &StaticFields<'_>, + variant_data: &VariantData, ) -> BlockOrExpr { - let expr = match summary { - Unnamed(_, IsTuple::No) => cx.expr_ident(trait_span, substr.type_ident), - Unnamed(fields, IsTuple::Yes) => { - let exprs = fields.iter().map(|sp| default_call(cx, *sp)).collect(); + let expr = match variant_data { + VariantData::Unit(_) => cx.expr_ident(trait_span, substr.type_ident), + VariantData::Tuple(fields, _) => { + let exprs = fields + .iter() + .map(|field| default_call(cx, field.span.with_ctxt(trait_span.ctxt()))) + .collect(); cx.expr_call_ident(trait_span, substr.type_ident, exprs) } - Named(fields) => { + VariantData::Struct { fields, .. } => { let default_fields = fields .iter() - .map(|&(ident, span, default_val)| { - let value = match default_val { - // We use `Default::default()`. - None => default_call(cx, span), + .map(|field| { + let span = field.span.with_ctxt(trait_span.ctxt()); + let value = if let Some(extras) = &field.extras + && let Some(default_val) = &extras.default + { // We use the field default const expression. - Some(val) => { - cx.expr(val.value.span, ast::ExprKind::ConstBlock(val.clone())) - } + cx.expr( + default_val.value.span, + ast::ExprKind::ConstBlock(default_val.clone()), + ) + } else { + // We use `Default::default()`. + default_call(cx, span) }; - cx.field_imm(span, ident, value) + cx.field_imm(span, field.ident.unwrap(), value) }) .collect(); cx.expr_struct_ident(trait_span, substr.type_ident, default_fields) diff --git a/tests/ui/derives/deriving-all-codegen.stdout b/tests/ui/derives/deriving-all-codegen.stdout index d0b387dbc8b25..6f7d817db00d7 100644 --- a/tests/ui/derives/deriving-all-codegen.stdout +++ b/tests/ui/derives/deriving-all-codegen.stdout @@ -46,7 +46,7 @@ impl ::core::fmt::Debug for Empty { #[automatically_derived] impl ::core::default::Default for Empty { #[inline] - fn default() -> Empty { Empty {} } + fn default() -> Empty { Empty } } #[automatically_derived] impl ::core::hash::Hash for Empty { From 4178dac3a87806d7887fa7363547773314a9b412 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Thu, 27 Aug 2026 12:39:06 +0000 Subject: [PATCH 8/8] remove `StaticFields` and `IsTuple` --- .../src/deriving/default.rs | 2 +- .../rustc_builtin_macros/src/deriving/from.rs | 2 +- .../src/deriving/generic/mod.rs | 72 ++----------------- 3 files changed, 7 insertions(+), 69 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs index eb9a302be31e0..9e65ae0b75cab 100644 --- a/compiler/rustc_builtin_macros/src/deriving/default.rs +++ b/compiler/rustc_builtin_macros/src/deriving/default.rs @@ -38,7 +38,7 @@ pub(crate) fn expand_deriving_default( fieldless_variants_strategy: FieldlessVariantsStrategy::Default, combine_substructure: combine_substructure(|cx, trait_span, substr| { match substr.fields { - StaticStruct(variant_data, _) => { + StaticStruct(variant_data) => { default_struct_substructure(cx, trait_span, substr, variant_data) } StaticEnum(enum_def) => { diff --git a/compiler/rustc_builtin_macros/src/deriving/from.rs b/compiler/rustc_builtin_macros/src/deriving/from.rs index 0758ff0269a96..eb8ddd10d4306 100644 --- a/compiler/rustc_builtin_macros/src/deriving/from.rs +++ b/compiler/rustc_builtin_macros/src/deriving/from.rs @@ -91,7 +91,7 @@ pub(crate) fn expand_deriving_from( let self_kw = Ident::new(kw::SelfUpper, span); let expr: Box = match substructure.fields { - SubstructureFields::StaticStruct(variant, _) => match variant { + SubstructureFields::StaticStruct(variant) => match variant { // Self { field: value } VariantData::Struct { .. } => cx.expr_struct_ident( span, diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 436881dbf2209..3298b4a583ff8 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -177,14 +177,13 @@ use std::ops::Not; use std::{iter, vec}; -pub(crate) use StaticFields::*; pub(crate) use SubstructureFields::*; pub(crate) use rustc_ast as ast; use rustc_ast::token::{IdentIsRaw, LitKind, Token, TokenKind}; use rustc_ast::tokenstream::{DelimSpan, Spacing, TokenTree}; use rustc_ast::{ - AnonConst, AttrArgs, BindingMode, ByRef, DelimArgs, EnumDef, Expr, GenericArg, - GenericParamKind, Generics, Mutability, PatKind, Safety, SelfKind, VariantData, + AttrArgs, BindingMode, ByRef, DelimArgs, EnumDef, Expr, GenericArg, GenericParamKind, Generics, + Mutability, PatKind, Safety, SelfKind, VariantData, }; use rustc_attr_ir::{Attribute, AttributeKind, ReprPacked}; use rustc_attr_parsing::AttributeParser; @@ -294,20 +293,6 @@ pub(crate) struct FieldInfo { pub maybe_scalar: bool, } -#[derive(Copy, Clone)] -pub(crate) enum IsTuple { - No, - Yes, -} - -/// Fields for a static method -pub(crate) enum StaticFields<'a> { - /// Tuple and unit structs/enum variants like this. - Unnamed(Vec, IsTuple), - /// Normal structs/struct variants. - Named(Vec<(Ident, Span, Option<&'a AnonConst>)>), -} - /// A summary of the possible sets of fields. pub(crate) enum SubstructureFields<'a> { /// A non-static method where `Self` is a struct. @@ -329,7 +314,7 @@ pub(crate) enum SubstructureFields<'a> { EnumDiscr(FieldInfo, Option>), /// A static method where `Self` is a struct. - StaticStruct(&'a ast::VariantData, StaticFields<'a>), + StaticStruct(&'a ast::VariantData), /// A static method where `Self` is an enum. StaticEnum(&'a ast::EnumDef), @@ -860,12 +845,12 @@ impl<'a> TraitDef<'a> { method_def.extract_arg_details(cx, self, type_ident, generics); let body = if from_scratch || method_def.is_static() { - method_def.expand_static_struct_method_body( + method_def.call_substructure_method( cx, self, - struct_def, type_ident, &nonselflike_args, + &StaticStruct(struct_def), ) } else { method_def.expand_struct_method_body( @@ -1133,25 +1118,6 @@ impl<'a> MethodDef<'a> { ) } - fn expand_static_struct_method_body( - &self, - cx: &ExtCtxt<'_>, - trait_: &TraitDef<'a>, - struct_def: &'a VariantData, - type_ident: Ident, - nonselflike_args: &[Box], - ) -> BlockOrExpr { - let summary = trait_.summarise_struct(cx, struct_def); - - self.call_substructure_method( - cx, - trait_, - type_ident, - nonselflike_args, - &StaticStruct(struct_def, summary), - ) - } - /// ``` /// #[derive(PartialEq)] /// # struct Dummy; @@ -1450,34 +1416,6 @@ impl<'a> MethodDef<'a> { // general helper methods. impl<'a> TraitDef<'a> { - fn summarise_struct(&self, cx: &ExtCtxt<'_>, struct_def: &'a VariantData) -> StaticFields<'a> { - let mut named_idents = Vec::new(); - let mut just_spans = Vec::new(); - for field in struct_def.fields() { - let sp = field.span.with_ctxt(self.span.ctxt()); - match field.ident { - Some(ident) => named_idents.push((ident, sp, field.default_value())), - _ => just_spans.push(sp), - } - } - - let is_tuple = match struct_def { - ast::VariantData::Tuple(..) => IsTuple::Yes, - _ => IsTuple::No, - }; - match (just_spans.is_empty(), named_idents.is_empty()) { - (false, false) => cx - .dcx() - .span_bug(self.span, "a struct with named and unnamed fields in generic `derive`"), - // named fields - (_, false) => Named(named_idents), - // unnamed fields - (false, _) => Unnamed(just_spans, is_tuple), - // empty - _ => Named(Vec::new()), - } - } - fn create_struct_patterns( &self, cx: &ExtCtxt<'_>,