diff --git a/compiler/rustc_builtin_macros/src/deriving/bounds.rs b/compiler/rustc_builtin_macros/src/deriving/bounds.rs deleted file mode 100644 index 48fdb4dd39ce2..0000000000000 --- a/compiler/rustc_builtin_macros/src/deriving/bounds.rs +++ /dev/null @@ -1,56 +0,0 @@ -use rustc_ast::{MetaItem, Safety}; -use rustc_expand::base::{Annotatable, 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: &Annotatable, - push: &mut dyn FnMut(Annotatable), - 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, - mitem: &MetaItem, - item: &Annotatable, - push: &mut dyn FnMut(Annotatable), - is_const: bool, -) { - let trait_def = TraitDef { - span, - path: path_std!(marker::ConstParamTy_), - skip_path_as_bound: false, - needs_copy_as_bound_if_packed: false, - additional_bounds: smallvec![ty::Ty::Path(path_std!(cmp::Eq))], - supports_unions: false, - 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/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs index b4374e32f6051..3257fc3437273 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_ast::{self as ast, Generics, ItemKind, 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}; @@ -11,9 +11,8 @@ use crate::deriving::path_std; pub(crate) fn expand_deriving_clone( cx: &ExtCtxt<'_>, span: Span, - mitem: &MetaItem, - item: &Annotatable, - push: &mut dyn FnMut(Annotatable), + item: &ast::Item, + push: &mut dyn FnMut(Box), is_const: bool, ) { // The simple form is `fn clone(&self) -> Self { *self }`, possibly with @@ -32,35 +31,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 @@ -82,7 +76,7 @@ pub(crate) fn expand_deriving_clone( document: false, }; - trivial_def.expand_ext(cx, mitem, item, push, true); + trivial_def.expand(cx, item, push); } let trait_def = TraitDef { @@ -94,7 +88,7 @@ pub(crate) fn expand_deriving_clone( supports_unions: true, methods: smallvec![MethodDef { name: sym::clone, - generics: Bounds::empty(), + generics: cx.empty_generics(span), explicit_self: true, nonself_args: SmallVec::new(), ret_ty: Self_, @@ -108,13 +102,13 @@ pub(crate) fn expand_deriving_clone( document: true, }; - trait_def.expand_ext(cx, mitem, item, push, is_simple) + trait_def.expand_ext(cx, item, push, is_simple) } fn cs_clone_simple( cx: &ExtCtxt<'_>, trait_span: Span, - substr: &Substructure<'_>, + substr: Substructure<'_>, is_union: bool, ) -> BlockOrExpr { let mut stmts = ThinVec::new(); @@ -155,7 +149,7 @@ fn cs_clone_simple( &[sym::clone, sym::AssertParamIsCopy], ); } else { - match *substr.fields { + match substr.fields { StaticStruct(vdata, ..) => { process_variant(vdata); } @@ -170,55 +164,41 @@ fn cs_clone_simple( BlockOrExpr::new_mixed(stmts, Some(cx.expr_deref(trait_span, cx.expr_self(trait_span)))) } -fn cs_clone(cx: &ExtCtxt<'_>, trait_span: Span, substr: &Substructure<'_>) -> BlockOrExpr { - let ctor_path; - let all_fields; +fn cs_clone(cx: &ExtCtxt<'_>, trait_span: Span, substr: Substructure<'_>) -> BlockOrExpr { let fn_path = cx.std_path(&[sym::clone, sym::Clone, sym::clone]); - let subcall = |cx: &ExtCtxt<'_>, field: &FieldInfo| { - let args = thin_vec![field.self_expr.clone()]; + let subcall = |field: FieldInfo| { + let args = thin_vec![field.self_expr]; cx.expr_call_global(field.span, fn_path.clone(), args) }; + let ctor_path; + let all_fields; let vdata; match substr.fields { Struct(vdata_, af) => { ctor_path = cx.path(trait_span, vec![substr.type_ident]); all_fields = af; - vdata = *vdata_; + vdata = vdata_; } EnumMatching(.., variant, af) => { ctor_path = cx.path(trait_span, vec![substr.type_ident, variant.ident]); all_fields = af; vdata = &variant.data; } - EnumDiscr(..) | AllFieldlessEnum(..) => { - cx.dcx().span_bug(trait_span, "enum discriminants in `derive(Clone)`") - } - StaticEnum(..) | StaticStruct(..) => { - cx.dcx().span_bug(trait_span, "associated function in `derive(Clone)`") - } + _ => cx.dcx().span_bug(trait_span, "unexpected substructure in `derive(Clone)`"), } let expr = match *vdata { VariantData::Struct { .. } => { let fields = all_fields - .iter() - .map(|field| { - let Some(ident) = field.name else { - cx.dcx().span_bug( - trait_span, - "unnamed field in normal struct in `derive(Clone)`", - ); - }; - let call = subcall(cx, field); - cx.field_imm(field.span, ident, call) - }) + .into_iter() + .map(|field| cx.field_imm(field.span, field.name.unwrap(), subcall(field))) .collect::>(); cx.expr_struct(trait_span, ctor_path, fields) } VariantData::Tuple(..) => { - let subcalls = all_fields.iter().map(|f| subcall(cx, f)).collect(); + let subcalls = all_fields.into_iter().map(subcall).collect(); let path = cx.expr_path(ctor_path); cx.expr_call(trait_span, path, subcalls) } diff --git a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs index 80296a43ee490..ab9037331050e 100644 --- a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs +++ b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs @@ -1,13 +1,13 @@ 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, + self as ast, GenericArg, GenericBound, GenericParamKind, Generics, ItemKind, TraitBoundModifiers, VariantData, WherePredicate, }; 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}; @@ -21,16 +21,13 @@ macro_rules! path { pub(crate) fn expand_deriving_coerce_pointee( cx: &ExtCtxt<'_>, span: Span, - _mitem: &MetaItem, - item: &Annotatable, - push: &mut dyn FnMut(Annotatable), + item: &ast::Item, + push: &mut dyn FnMut(Box), _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, _) @@ -104,7 +101,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(), @@ -144,7 +141,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); @@ -167,7 +164,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 @@ -322,7 +319,7 @@ pub(crate) fn expand_deriving_coerce_pointee( // Add the impl blocks for `DispatchFromDyn` and `CoerceUnsized`. let gen_args = vec![GenericArg::Type(alt_self_type)]; add_impl_block(impl_generics.clone(), sym::DispatchFromDyn, gen_args.clone()); - add_impl_block(impl_generics.clone(), sym::CoerceUnsized, gen_args); + add_impl_block(impl_generics, sym::CoerceUnsized, gen_args); } fn contains_maybe_sized_bound_on_pointee(predicates: &[WherePredicate], pointee: Symbol) -> bool { @@ -330,10 +327,8 @@ fn contains_maybe_sized_bound_on_pointee(predicates: &[WherePredicate], pointee: if let ast::WherePredicateKind::BoundPredicate(bound) = &bound.kind && bound.bounded_ty.kind.is_simple_path().is_some_and(|name| name == pointee) { - for bound in &bound.bounds { - if is_maybe_sized_bound(bound) { - return true; - } + if contains_maybe_sized_bound(&bound.bounds) { + return true; } } } diff --git a/compiler/rustc_builtin_macros/src/deriving/const_param_ty.rs b/compiler/rustc_builtin_macros/src/deriving/const_param_ty.rs new file mode 100644 index 0000000000000..8034a3e9b0b16 --- /dev/null +++ b/compiler/rustc_builtin_macros/src/deriving/const_param_ty.rs @@ -0,0 +1,30 @@ +use rustc_ast::Safety; +use rustc_expand::base::ExtCtxt; +use rustc_span::Span; + +use crate::deriving::generic::*; +use crate::deriving::path_std; + +pub(crate) fn expand_deriving_const_param_ty( + cx: &ExtCtxt<'_>, + span: Span, + item: &ast::Item, + push: &mut dyn FnMut(Box), + is_const: bool, +) { + let trait_def = TraitDef { + span, + path: path_std!(marker::ConstParamTy_), + skip_path_as_bound: false, + needs_copy_as_bound_if_packed: false, + additional_bounds: smallvec![ty::Ty::Path(path_std!(cmp::Eq))], + supports_unions: false, + methods: SmallVec::new(), + associated_types: SmallVec::new(), + is_const, + safety: Safety::Default, + document: true, + }; + + trait_def.expand(cx, item, push); +} 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..bae4bd98df465 --- /dev/null +++ b/compiler/rustc_builtin_macros/src/deriving/copy.rs @@ -0,0 +1,30 @@ +use rustc_ast::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, + 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, item, push); +} diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs index 94e0b704e6c08..e694502d607e8 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, MetaItem, Safety}; -use rustc_expand::base::{Annotatable, ExtCtxt}; +use rustc_ast::{self as ast, EnumDef, Safety}; +use rustc_expand::base::ExtCtxt; use rustc_session::config::FmtDebug; use rustc_span::{Ident, Span, Symbol, sym}; use thin_vec::{ThinVec, thin_vec}; @@ -11,9 +11,8 @@ use crate::deriving::path_std; pub(crate) fn expand_deriving_debug( cx: &ExtCtxt<'_>, span: Span, - mitem: &MetaItem, - item: &Annotatable, - push: &mut dyn FnMut(Annotatable), + item: &ast::Item, + push: &mut dyn FnMut(Box), is_const: bool, ) { // &mut ::std::fmt::Formatter @@ -28,7 +27,7 @@ pub(crate) fn expand_deriving_debug( supports_unions: false, methods: smallvec![MethodDef { name: sym::fmt, - generics: Bounds::empty(), + generics: cx.empty_generics(span), explicit_self: true, nonself_args: smallvec![(fmtr, sym::character('f'))], ret_ty: Path(path_std!(fmt::Result)), @@ -42,10 +41,10 @@ pub(crate) fn expand_deriving_debug( safety: Safety::Default, document: true, }; - trait_def.expand(cx, mitem, item, push) + trait_def.expand(cx, item, push) } -fn show_substructure(cx: &ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr { +fn show_substructure(cx: &ExtCtxt<'_>, span: Span, substr: Substructure<'_>) -> BlockOrExpr { // We want to make sure we have the ctxt set so that we can use unstable methods let span = cx.with_def_site_ctxt(span); @@ -55,12 +54,10 @@ fn show_substructure(cx: &ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> } let (ident, vdata, fields) = match substr.fields { - Struct(vdata, fields) => (substr.type_ident, *vdata, fields), + Struct(vdata, fields) => (substr.type_ident, vdata, fields), EnumMatching(v, fields) => (v.ident, &v.data, fields), AllFieldlessEnum(enum_def) => return show_fieldless_enum(cx, span, enum_def, substr), - EnumDiscr(..) | StaticStruct(..) | StaticEnum(..) => { - cx.dcx().span_bug(span, "nonsensical .fields in `#[derive(Debug)]`") - } + _ => cx.dcx().span_bug(span, "unexpected substructure in `derive(Debug)`"), }; let name = cx.expr_str(span, ident.name); @@ -88,20 +85,15 @@ fn show_substructure(cx: &ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> // The number of fields that can be handled without an array. const CUTOFF: usize = 5; - fn expr_for_field( - cx: &ExtCtxt<'_>, - field: &FieldInfo, - index: usize, - len: usize, - ) -> Box { - if index < len - 1 { + let expr_for_field = |field: &FieldInfo, index: usize| -> Box { + if index < fields.len() - 1 { field.self_expr.clone() } else { // Unsized types need an extra indirection, but only the last field // may be unsized. cx.expr_addr_of(field.span, field.self_expr.clone()) } - } + }; if fields.is_empty() { // Special case for no fields. @@ -126,7 +118,7 @@ fn show_substructure(cx: &ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> args.push(name); } - let field = expr_for_field(cx, field, i, fields.len()); + let field = expr_for_field(field, i); args.push(field); } let expr = cx.expr_call_global(span, fn_path_debug, args); @@ -142,7 +134,7 @@ fn show_substructure(cx: &ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> name_exprs.push(cx.expr_str(field.span, field.name.unwrap().name)); } - let field = expr_for_field(cx, field, i, fields.len()); + let field = expr_for_field(field, i); value_exprs.push(field); } @@ -224,7 +216,7 @@ fn show_fieldless_enum( cx: &ExtCtxt<'_>, span: Span, def: &EnumDef, - substr: &Substructure<'_>, + substr: Substructure<'_>, ) -> BlockOrExpr { let fmt = substr.nonselflike_args[0].clone(); let arms = def diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs index 3e4c5f1dcfa53..f9f9af4e9f012 100644 --- a/compiler/rustc_builtin_macros/src/deriving/default.rs +++ b/compiler/rustc_builtin_macros/src/deriving/default.rs @@ -1,8 +1,8 @@ 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_expand::base::{DummyResult, ExtCtxt}; use rustc_span::{ErrorGuaranteed, Ident, Span, kw, sym}; use smallvec::SmallVec; use thin_vec::{ThinVec, thin_vec}; @@ -14,12 +14,11 @@ use crate::diagnostics; pub(crate) fn expand_deriving_default( cx: &ExtCtxt<'_>, span: Span, - mitem: &ast::MetaItem, - item: &Annotatable, - push: &mut dyn FnMut(Annotatable), + item: &ast::Item, + push: &mut dyn FnMut(Box), is_const: bool, ) { - item.visit_with(&mut DetectNonVariantDefaultAttr { cx }); + DetectNonVariantDefaultAttr { cx }.visit_item(item); let trait_def = TraitDef { span, @@ -30,7 +29,7 @@ pub(crate) fn expand_deriving_default( supports_unions: false, methods: smallvec![MethodDef { name: kw::Default, - generics: Bounds::empty(), + generics: cx.empty_generics(span), explicit_self: false, nonself_args: SmallVec::new(), ret_ty: Self_, @@ -38,13 +37,15 @@ 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()) + default_enum_substructure(cx, trait_span, enum_def, item.span) } - _ => cx.dcx().span_bug(trait_span, "method in `derive(Default)`"), + _ => cx + .dcx() + .span_bug(trait_span, "unexpected substructure in `derive(Default)`"), } }), }], @@ -53,7 +54,7 @@ pub(crate) fn expand_deriving_default( safety: Safety::Default, document: true, }; - trait_def.expand(cx, mitem, item, push) + trait_def.expand(cx, item, push) } fn default_call(cx: &ExtCtxt<'_>, span: Span) -> Box { @@ -65,28 +66,36 @@ fn default_call(cx: &ExtCtxt<'_>, span: Span) -> Box { fn default_struct_substructure( cx: &ExtCtxt<'_>, trait_span: Span, - substr: &Substructure<'_>, - summary: &StaticFields<'_>, + substr: Substructure<'_>, + 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) @@ -308,7 +317,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 +332,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/cmp/eq.rs b/compiler/rustc_builtin_macros/src/deriving/eq.rs similarity index 86% rename from compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs rename to compiler/rustc_builtin_macros/src/deriving/eq.rs index 440360ca85d7d..eaf9298fc10c7 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/eq.rs @@ -1,6 +1,6 @@ -use rustc_ast::{self as ast, MetaItem, Safety}; +use rustc_ast::{self as ast, 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}; @@ -11,9 +11,8 @@ use crate::deriving::path_std; pub(crate) fn expand_deriving_eq( cx: &ExtCtxt<'_>, span: Span, - mitem: &MetaItem, - item: &Annotatable, - push: &mut dyn FnMut(Annotatable), + item: &ast::Item, + push: &mut dyn FnMut(Box), is_const: bool, ) { let span = cx.with_def_site_ctxt(span); @@ -27,7 +26,7 @@ pub(crate) fn expand_deriving_eq( supports_unions: true, methods: smallvec![MethodDef { name: sym::assert_fields_are_eq, - generics: Bounds::empty(), + generics: cx.empty_generics(span), explicit_self: true, nonself_args: smallvec![], ret_ty: Unit, @@ -46,14 +45,10 @@ pub(crate) fn expand_deriving_eq( safety: Safety::Default, document: true, }; - trait_def.expand_ext(cx, mitem, item, push, true) + trait_def.expand_ext(cx, item, push, true) } -fn cs_total_eq_assert( - cx: &ExtCtxt<'_>, - trait_span: Span, - substr: &Substructure<'_>, -) -> BlockOrExpr { +fn cs_total_eq_assert(cx: &ExtCtxt<'_>, trait_span: Span, substr: Substructure<'_>) -> BlockOrExpr { let mut stmts = ThinVec::new(); let mut seen_type_names = FxHashSet::default(); let mut process_variant = |variant: &ast::VariantData| { @@ -78,7 +73,7 @@ fn cs_total_eq_assert( } }; - match *substr.fields { + match substr.fields { StaticStruct(vdata, ..) => { process_variant(vdata); } diff --git a/compiler/rustc_builtin_macros/src/deriving/from.rs b/compiler/rustc_builtin_macros/src/deriving/from.rs index 9824ab5a225b7..0b28df9850097 100644 --- a/compiler/rustc_builtin_macros/src/deriving/from.rs +++ b/compiler/rustc_builtin_macros/src/deriving/from.rs @@ -1,11 +1,11 @@ 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; -use crate::deriving::generic::ty::{Bounds, Path, PathKind, Ty}; +use crate::deriving::generic::ty::{Path, PathKind, Ty}; use crate::deriving::generic::*; use crate::deriving::pathvec; use crate::diagnostics; @@ -15,15 +15,10 @@ use crate::diagnostics; pub(crate) fn expand_deriving_from( cx: &ExtCtxt<'_>, span: Span, - mitem: &ast::MetaItem, - annotatable: &Annotatable, - push: &mut dyn FnMut(Annotatable), + item: &ast::Item, + push: &mut dyn FnMut(Box), 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]) @@ -79,7 +74,7 @@ pub(crate) fn expand_deriving_from( supports_unions: false, methods: smallvec![MethodDef { name: sym::from, - generics: Bounds { bounds: vec![] }, + generics: cx.empty_generics(span), explicit_self: false, nonself_args: smallvec![(from_type, sym::value)], ret_ty: Ty::Self_, @@ -95,7 +90,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, @@ -127,5 +122,5 @@ pub(crate) fn expand_deriving_from( document: true, }; - from_trait_def.expand(cx, mitem, annotatable, push); + from_trait_def.expand(cx, 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..72c3252f7854e 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -177,21 +177,21 @@ 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::{ - self as ast, AnonConst, AttrArgs, BindingMode, ByRef, DelimArgs, EnumDef, Expr, GenericArg, - GenericParamKind, Generics, Mutability, PatKind, Safety, SelfKind, VariantData, + AttrArgs, DelimArgs, EnumDef, Expr, GenericArg, GenericParamKind, Generics, Safety, SelfKind, + VariantData, }; 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}; -use ty::{Bounds, Path, Ref, Self_, Ty}; +use ty::{Path, Ref, Self_, Ty}; use crate::{deriving, diagnostics}; @@ -234,7 +234,7 @@ pub(crate) struct MethodDef<'a> { /// name of the method pub name: Symbol, /// List of generics, e.g., `R: rand::Rng` - pub generics: Bounds, + pub generics: Generics, /// Is there is a `&self` argument? If not, it is a static function. pub explicit_self: bool, @@ -275,7 +275,7 @@ pub(crate) struct Substructure<'a> { /// Verbatim access to any non-selflike arguments, i.e. arguments that /// don't have type `&Self`. pub nonselflike_args: &'a [Box], - pub fields: &'a SubstructureFields<'a>, + pub fields: SubstructureFields<'a>, } /// Summary of the relevant parts of a struct/enum field. @@ -293,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. @@ -328,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), @@ -337,10 +323,10 @@ pub(crate) enum SubstructureFields<'a> { /// Combine the values of all the fields together. The last argument is /// all the fields of all the structures. pub(crate) type CombineSubstructureFunc<'a> = - Box, Span, &Substructure<'_>) -> BlockOrExpr + 'a>; + Box, Span, Substructure<'_>) -> BlockOrExpr + 'a>; pub(crate) fn combine_substructure<'a>( - f: impl Fn(&ExtCtxt<'_>, Span, &Substructure<'_>) -> BlockOrExpr + 'a, + f: impl Fn(&ExtCtxt<'_>, Span, Substructure<'_>) -> BlockOrExpr + 'a, ) -> CombineSubstructureFunc<'a> { Box::new(f) } @@ -472,83 +458,71 @@ impl<'a> TraitDef<'a> { pub(crate) fn expand( self, cx: &ExtCtxt<'_>, - mitem: &ast::MetaItem, - item: &'a Annotatable, - push: &mut dyn FnMut(Annotatable), + item: &'a ast::Item, + push: &mut dyn FnMut(Box), ) { - self.expand_ext(cx, mitem, item, push, false); + self.expand_ext(cx, item, push, false); } pub(crate) fn expand_ext( self, cx: &ExtCtxt<'_>, - mitem: &ast::MetaItem, - item: &'a Annotatable, - push: &mut dyn FnMut(Annotatable), + item: &'a ast::Item, + push: &mut dyn FnMut(Box), 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: self.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(newitem); } /// Given that we are deriving a trait `DerivedTrait` for a type like: @@ -591,8 +565,8 @@ impl<'a> TraitDef<'a> { cx: &ExtCtxt<'_>, type_ident: Ident, generics: &Generics, - field_tys: Vec<&ast::Ty>, - methods: Vec>, + field_tys: impl Iterator, + methods: impl Iterator>, is_packed: bool, ) -> Box { let trait_path = self.path.to_path(cx, self.span, type_ident, generics); @@ -845,7 +819,7 @@ impl<'a> TraitDef<'a> { })), constness: if self.is_const { ast::Const::Yes(DUMMY_SP) } else { ast::Const::No }, self_ty: self_type, - items: methods.into_iter().chain(associated_types).collect(), + items: methods.chain(associated_types).collect(), }), ) } @@ -859,46 +833,42 @@ impl<'a> TraitDef<'a> { from_scratch: bool, is_packed: bool, ) -> Box { - let field_tys = Vec::from_iter(struct_def.fields().iter().map(|field| &*field.ty)); + let field_tys = struct_def.fields().iter().map(|field| &*field.ty); - let methods = self - .methods - .iter() - .map(|method_def| { - let (explicit_self, selflike_args, nonselflike_args, nonself_arg_tys) = - method_def.extract_arg_details(cx, self, type_ident, generics); + let methods = self.methods.iter().map(|method_def| { + let ArgDetails { explicit_self, selflike_args, nonselflike_args, nonself_arg_tys } = + 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( - cx, - self, - struct_def, - type_ident, - &nonselflike_args, - ) - } else { - method_def.expand_struct_method_body( - cx, - self, - struct_def, - type_ident, - &selflike_args, - &nonselflike_args, - is_packed, - ) - }; - - method_def.create_method( + let body = if from_scratch || method_def.is_static() { + method_def.call_substructure_method( cx, self, type_ident, - generics, - explicit_self, - nonself_arg_tys, - body, + &nonselflike_args, + StaticStruct(struct_def), ) - }) - .collect(); + } else { + method_def.expand_struct_method_body( + cx, + self, + struct_def, + type_ident, + &selflike_args, + &nonselflike_args, + is_packed, + ) + }; + + method_def.create_method( + cx, + self, + type_ident, + generics, + explicit_self, + nonself_arg_tys, + body, + ) + }); self.create_derived_impl(cx, type_ident, generics, field_tys, methods, is_packed) } @@ -911,57 +881,69 @@ impl<'a> TraitDef<'a> { generics: &Generics, from_scratch: bool, ) -> Box { - let field_tys = Vec::from_iter( - enum_def - .variants - .iter() - .flat_map(|variant| variant.data.fields()) - .map(|field| &*field.ty), - ); - - let methods = self - .methods + let field_tys = enum_def + .variants .iter() - .map(|method_def| { - let (explicit_self, selflike_args, nonselflike_args, nonself_arg_tys) = - method_def.extract_arg_details(cx, self, type_ident, generics); + .flat_map(|variant| variant.data.fields()) + .map(|field| &*field.ty); - let body = if from_scratch || method_def.is_static() { - method_def.expand_static_enum_method_body( - cx, - self, - enum_def, - type_ident, - &nonselflike_args, - ) - } else { - method_def.expand_enum_method_body( - cx, - self, - enum_def, - type_ident, - selflike_args, - &nonselflike_args, - ) - }; + let methods = self.methods.iter().filter_map(|method_def| { + let ArgDetails { explicit_self, selflike_args, nonselflike_args, nonself_arg_tys } = + method_def.extract_arg_details(cx, self, type_ident, generics); - method_def.create_method( + let body = if from_scratch || method_def.is_static() { + method_def.call_substructure_method( cx, self, type_ident, - generics, - explicit_self, - nonself_arg_tys, - body, + &nonselflike_args, + StaticEnum(enum_def), ) - }) - .collect(); + } else { + method_def.expand_enum_method_body( + cx, + self, + enum_def, + type_ident, + selflike_args, + &nonselflike_args, + ) + }; + + // `assert_fields_are_eq` has an empty default implementation + if body.0.is_empty() && body.1.is_none() && method_def.name == sym::assert_fields_are_eq + { + return None; + } + + Some(method_def.create_method( + cx, + self, + type_ident, + generics, + explicit_self, + nonself_arg_tys, + body, + )) + }); let is_packed = false; // enums are never packed self.create_derived_impl(cx, type_ident, generics, field_tys, methods, is_packed) } } +struct ArgDetails { + /// The `&self` arg, if present. + explicit_self: Option, + /// Expressions for `&self` (if present) and also any other + /// args with the same type (e.g. the `other` arg in `PartialEq::eq`). + selflike_args: ThinVec>, + /// Expressions for all the remaining args. + nonselflike_args: Vec>, + /// Additional information about all the args other than `&self`. + nonself_arg_tys: Vec<(Ident, Box)>, +} + impl<'a> MethodDef<'a> { fn call_substructure_method( &self, @@ -969,33 +951,25 @@ impl<'a> MethodDef<'a> { trait_: &TraitDef<'_>, type_ident: Ident, nonselflike_args: &[Box], - fields: &SubstructureFields<'_>, + fields: SubstructureFields<'_>, ) -> BlockOrExpr { let span = trait_.span; let substructure = Substructure { type_ident, nonselflike_args, fields }; let f: &CombineSubstructureFunc<'_> = &self.combine_substructure; - f(cx, span, &substructure) + f(cx, span, substructure) } fn is_static(&self) -> bool { !self.explicit_self } - // The return value includes: - // - explicit_self: The `&self` arg, if present. - // - selflike_args: Expressions for `&self` (if present) and also any other - // args with the same type (e.g. the `other` arg in `PartialEq::eq`). - // - nonselflike_args: Expressions for all the remaining args. - // - nonself_arg_tys: Additional information about all the args other than - // `&self`. fn extract_arg_details( &self, cx: &ExtCtxt<'_>, trait_: &TraitDef<'_>, type_ident: Ident, generics: &Generics, - ) -> (Option, ThinVec>, Vec>, Vec<(Ident, Box)>) - { + ) -> ArgDetails { let mut selflike_args = ThinVec::new(); let mut nonselflike_args = Vec::new(); let mut nonself_arg_tys = Vec::new(); @@ -1022,7 +996,7 @@ impl<'a> MethodDef<'a> { } } - (explicit_self, selflike_args, nonselflike_args, nonself_arg_tys) + ArgDetails { explicit_self, selflike_args, nonselflike_args, nonself_arg_tys } } fn create_method( @@ -1037,7 +1011,7 @@ impl<'a> MethodDef<'a> { ) -> Box { let span = trait_.span; // Create the generics that aren't for `Self`. - let fn_generics = self.generics.to_generics(cx, span, type_ident, generics); + let fn_generics = self.generics.clone(); let args = { let self_arg = explicit_self.map(|explicit_self| { @@ -1138,26 +1112,7 @@ impl<'a> MethodDef<'a> { trait_, type_ident, nonselflike_args, - &Struct(struct_def, selflike_fields), - ) - } - - 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), + Struct(struct_def, selflike_fields), ) } @@ -1287,7 +1242,7 @@ impl<'a> MethodDef<'a> { trait_, type_ident, nonselflike_args, - &EnumDiscr(discr_field, None), + EnumDiscr(discr_field, None), ); discr_let_stmts.append(&mut discr_check.0); return BlockOrExpr(discr_let_stmts, discr_check.1); @@ -1298,7 +1253,7 @@ impl<'a> MethodDef<'a> { trait_, type_ident, nonselflike_args, - &AllFieldlessEnum(enum_def), + AllFieldlessEnum(enum_def), ); } FieldlessVariantsStrategy::Default => (), @@ -1311,7 +1266,7 @@ impl<'a> MethodDef<'a> { trait_, type_ident, nonselflike_args, - &EnumMatching(variant, Vec::new()), + EnumMatching(variant, Vec::new()), ); } } @@ -1332,14 +1287,8 @@ impl<'a> MethodDef<'a> { let sp = variant.span.with_ctxt(trait_.span.ctxt()); let variant_path = cx.path(sp, vec![type_ident, variant.ident]); - let by_ref = ByRef::No; // because enums can't be repr(packed) - let mut subpats = trait_.create_struct_patterns( - cx, - variant_path, - &variant.data, - &prefixes, - by_ref, - ); + let mut subpats = + trait_.create_struct_patterns(cx, variant_path, &variant.data, &prefixes); // `(VariantK, VariantK, ...)` or just `VariantK`. let single_pat = if subpats.len() == 1 { @@ -1363,7 +1312,7 @@ impl<'a> MethodDef<'a> { trait_, type_ident, nonselflike_args, - &substructure, + substructure, ) .into_expr(cx, span); @@ -1384,7 +1333,7 @@ impl<'a> MethodDef<'a> { trait_, type_ident, nonselflike_args, - &EnumMatching(v, Vec::new()), + EnumMatching(v, Vec::new()), ) .into_expr(cx, span), ) @@ -1430,7 +1379,7 @@ impl<'a> MethodDef<'a> { trait_, type_ident, nonselflike_args, - &EnumDiscr(discr_field, Some(get_match_expr(selflike_args))), + EnumDiscr(discr_field, Some(get_match_expr(selflike_args))), ); discr_let_stmts.append(&mut discr_check_plus_match.0); BlockOrExpr(discr_let_stmts, discr_check_plus_match.1) @@ -1438,62 +1387,16 @@ impl<'a> MethodDef<'a> { BlockOrExpr(ThinVec::new(), Some(get_match_expr(selflike_args))) } } - - fn expand_static_enum_method_body( - &self, - cx: &ExtCtxt<'_>, - trait_: &TraitDef<'_>, - enum_def: &EnumDef, - type_ident: Ident, - nonselflike_args: &[Box], - ) -> BlockOrExpr { - self.call_substructure_method( - cx, - trait_, - type_ident, - nonselflike_args, - &StaticEnum(enum_def), - ) - } } // 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<'_>, struct_path: ast::Path, struct_def: &'a VariantData, prefixes: &[String], - by_ref: ByRef, ) -> ThinVec { prefixes .iter() @@ -1503,42 +1406,28 @@ impl<'a> TraitDef<'a> { let sp = struct_field.span.with_ctxt(self.span.ctxt()); let ident = self.mk_pattern_ident(prefix, i); let path = ident.with_span_pos(sp); - ( - sp, - struct_field.ident, - cx.pat( - path.span, - PatKind::Ident(BindingMode(by_ref, Mutability::Not), path, None), - ), - ) + (struct_field.ident, cx.pat_ident(path.span, path)) }); let struct_path = struct_path.clone(); match *struct_def { VariantData::Struct { .. } => { let field_pats = pieces_iter - .map(|(sp, ident, pat)| { - if ident.is_none() { - cx.dcx().span_bug( - sp, - "a braced struct with unnamed fields in `derive`", - ); - } - ast::PatField { - ident: ident.unwrap(), - is_shorthand: false, - attrs: ast::AttrVec::new(), - id: ast::DUMMY_NODE_ID, - span: pat.span.with_ctxt(self.span.ctxt()), - pat: Box::new(pat), - is_placeholder: false, - } + .map(|(ident, pat)| ast::PatField { + ident: ident + .expect("a braced struct with unnamed fields in `derive`"), + is_shorthand: false, + attrs: ast::AttrVec::new(), + id: ast::DUMMY_NODE_ID, + span: pat.span.with_ctxt(self.span.ctxt()), + pat: Box::new(pat), + is_placeholder: false, }) .collect(); cx.pat_struct(self.span, struct_path, field_pats) } VariantData::Tuple(..) => { - let subpats = pieces_iter.map(|(_, _, subpat)| subpat).collect(); + let subpats = pieces_iter.map(|(_, subpat)| subpat).collect(); cx.pat_tuple_struct(self.span, struct_path, subpats) } VariantData::Unit(..) => cx.pat_path(self.span, struct_path), @@ -1635,10 +1524,10 @@ impl<'a> TraitDef<'a> { /// The function passed to `cs_fold` is called repeatedly with a value of this /// type. It describes one part of the code generation. The result is always an /// expression. -pub(crate) enum CsFold<'a> { +pub(crate) enum CsFold { /// The basic case: a field expression for one or more selflike args. E.g. /// for `PartialEq::eq` this is something like `self.x == other.x`. - Single(&'a FieldInfo), + Single(FieldInfo), /// The combination of two field expressions. E.g. for `PartialEq::eq` this /// is something like ` && `. @@ -1654,52 +1543,48 @@ pub(crate) fn cs_fold( use_foldl: bool, cx: &ExtCtxt<'_>, trait_span: Span, - substructure: &Substructure<'_>, + substructure: Substructure<'_>, mut f: F, ) -> Box where - F: FnMut(&ExtCtxt<'_>, CsFold<'_>) -> Box, + F: FnMut(&ExtCtxt<'_>, CsFold) -> Box, { match substructure.fields { - EnumMatching(.., all_fields) | Struct(_, all_fields) => { + EnumMatching(.., mut all_fields) | Struct(_, mut all_fields) => { if all_fields.is_empty() { return f(cx, CsFold::Fieldless); } - let (base_field, rest) = if use_foldl { - all_fields.split_first().unwrap() - } else { - all_fields.split_last().unwrap() - }; + let base_field = + if use_foldl { all_fields.remove(0) } else { all_fields.pop().unwrap() }; + let rest = all_fields; let base_expr = f(cx, CsFold::Single(base_field)); - let op = |old, field: &FieldInfo| { + let op = |old, field: FieldInfo| { + let span = field.span; let new = f(cx, CsFold::Single(field)); - f(cx, CsFold::Combine(field.span, old, new)) + f(cx, CsFold::Combine(span, old, new)) }; if use_foldl { - rest.iter().fold(base_expr, op) + rest.into_iter().fold(base_expr, op) } else { - rest.iter().rfold(base_expr, op) + rest.into_iter().rfold(base_expr, op) } } EnumDiscr(discr_field, match_expr) => { let discr_check_expr = f(cx, CsFold::Single(discr_field)); if let Some(match_expr) = match_expr { if use_foldl { - f(cx, CsFold::Combine(trait_span, discr_check_expr, match_expr.clone())) + f(cx, CsFold::Combine(trait_span, discr_check_expr, match_expr)) } else { - f(cx, CsFold::Combine(trait_span, match_expr.clone(), discr_check_expr)) + f(cx, CsFold::Combine(trait_span, match_expr, discr_check_expr)) } } else { discr_check_expr } } - StaticEnum(..) | StaticStruct(..) => { - cx.dcx().span_bug(trait_span, "static function in `derive`") - } - AllFieldlessEnum(..) => cx.dcx().span_bug(trait_span, "fieldless enum in `derive`"), + _ => cx.dcx().span_bug(trait_span, "unexpected substructure in `derive`"), } } diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs index 6e504534ba26d..98ad5b8faf52b 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs @@ -131,56 +131,3 @@ impl Ty { } } } - -fn mk_ty_param( - cx: &ExtCtxt<'_>, - span: Span, - name: Symbol, - bounds: &[Path], - self_ident: Ident, - self_generics: &Generics, -) -> ast::GenericParam { - let bounds = bounds - .iter() - .map(|b| { - let path = b.to_path(cx, span, self_ident, self_generics); - cx.trait_bound(path, false) - }) - .collect(); - cx.typaram(span, Ident::new(name, span), bounds, None) -} - -/// Bounds on type parameters. -#[derive(Clone)] -pub(crate) struct Bounds { - pub bounds: Vec<(Symbol, Vec)>, -} - -impl Bounds { - pub(crate) fn empty() -> Bounds { - Bounds { bounds: Vec::new() } - } - pub(crate) fn to_generics( - &self, - cx: &ExtCtxt<'_>, - span: Span, - self_ty: Ident, - self_generics: &Generics, - ) -> Generics { - let params = self - .bounds - .iter() - .map(|&(name, ref bounds)| mk_ty_param(cx, span, name, bounds, self_ty, self_generics)) - .collect(); - - Generics { - params, - where_clause: ast::WhereClause { - has_where_token: false, - predicates: ThinVec::new(), - span, - }, - span, - } - } -} diff --git a/compiler/rustc_builtin_macros/src/deriving/hash.rs b/compiler/rustc_builtin_macros/src/deriving/hash.rs index f1931aa90a435..b6a87851254fc 100644 --- a/compiler/rustc_builtin_macros/src/deriving/hash.rs +++ b/compiler/rustc_builtin_macros/src/deriving/hash.rs @@ -1,7 +1,7 @@ -use rustc_ast::{MetaItem, Mutability, Safety}; -use rustc_expand::base::{Annotatable, ExtCtxt}; -use rustc_span::{Span, sym}; -use thin_vec::thin_vec; +use rustc_ast::{Mutability, Safety}; +use rustc_expand::base::ExtCtxt; +use rustc_span::{Ident, Span, sym}; +use thin_vec::{ThinVec, thin_vec}; use crate::deriving::generic::ty::*; use crate::deriving::generic::*; @@ -10,9 +10,8 @@ use crate::deriving::path_std; pub(crate) fn expand_deriving_hash( cx: &ExtCtxt<'_>, span: Span, - mitem: &MetaItem, - item: &Annotatable, - push: &mut dyn FnMut(Annotatable), + item: &ast::Item, + push: &mut dyn FnMut(Box), is_const: bool, ) { let path = path_std!(hash::Hash); @@ -20,6 +19,18 @@ pub(crate) fn expand_deriving_hash( let typaram = sym::__H; let arg = Path::new_local(typaram); + + let param = { + let path = cx.path_all(span, false, cx.std_path(&[sym::hash, sym::Hasher]), Vec::new()); + cx.typaram(span, Ident::new(typaram, span), thin_vec![cx.trait_bound(path, false)], None) + }; + + let generics = ast::Generics { + params: thin_vec![param], + where_clause: ast::WhereClause { has_where_token: false, predicates: ThinVec::new(), span }, + span, + }; + let hash_trait_def = TraitDef { span, path, @@ -29,7 +40,7 @@ pub(crate) fn expand_deriving_hash( supports_unions: false, methods: smallvec![MethodDef { name: sym::hash, - generics: Bounds { bounds: vec![(typaram, vec![path_std!(hash::Hasher)])] }, + generics, explicit_self: true, nonself_args: smallvec![(Ref(Box::new(Path(arg)), Mutability::Mut), sym::state)], ret_ty: Unit, @@ -43,10 +54,10 @@ pub(crate) fn expand_deriving_hash( document: true, }; - hash_trait_def.expand(cx, mitem, item, push); + hash_trait_def.expand(cx, item, push); } -fn hash_substructure(cx: &ExtCtxt<'_>, trait_span: Span, substr: &Substructure<'_>) -> BlockOrExpr { +fn hash_substructure(cx: &ExtCtxt<'_>, trait_span: Span, substr: Substructure<'_>) -> BlockOrExpr { let [state_expr] = substr.nonselflike_args else { cx.dcx().span_bug(trait_span, "incorrect number of arguments in `derive(Hash)`"); }; @@ -60,15 +71,15 @@ fn hash_substructure(cx: &ExtCtxt<'_>, trait_span: Span, substr: &Substructure<' let (stmts, match_expr) = match substr.fields { Struct(_, fields) | EnumMatching(.., fields) => { let stmts = - fields.iter().map(|field| call_hash(field.span, field.self_expr.clone())).collect(); + fields.into_iter().map(|field| call_hash(field.span, field.self_expr)).collect(); (stmts, None) } EnumDiscr(discr_field, match_expr) => { assert!(discr_field.other_selflike_exprs.is_empty()); - let stmts = thin_vec![call_hash(discr_field.span, discr_field.self_expr.clone())]; - (stmts, match_expr.clone()) + let stmts = thin_vec![call_hash(discr_field.span, discr_field.self_expr)]; + (stmts, match_expr) } - _ => cx.dcx().span_bug(trait_span, "impossible substructure in `derive(Hash)`"), + _ => cx.dcx().span_bug(trait_span, "unexpected substructure in `derive(Hash)`"), }; BlockOrExpr::new_mixed(stmts, match_expr) diff --git a/compiler/rustc_builtin_macros/src/deriving/mod.rs b/compiler/rustc_builtin_macros/src/deriving/mod.rs index 602af919bd4f2..a1b1d56664f22 100644 --- a/compiler/rustc_builtin_macros/src/deriving/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/mod.rs @@ -14,28 +14,24 @@ 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; 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; pub(crate) type BuiltinDeriveFn = - fn(&ExtCtxt<'_>, Span, &MetaItem, &Annotatable, &mut dyn FnMut(Annotatable), bool); + fn(&ExtCtxt<'_>, Span, &ast::Item, &mut dyn FnMut(Box), bool); pub(crate) struct BuiltinDerive(pub(crate) BuiltinDeriveFn); @@ -44,7 +40,7 @@ impl MultiItemModifier for BuiltinDerive { &self, ecx: &mut ExtCtxt<'_>, span: Span, - meta_item: &MetaItem, + _: &MetaItem, item: Annotatable, is_derive_const: bool, ) -> ExpandResult, Annotatable> { @@ -58,26 +54,22 @@ impl MultiItemModifier for BuiltinDerive { (self.0)( ecx, span, - meta_item, - &Annotatable::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.expect_item()), - span, - }))); - }, + &item, + &mut |a| items.push(Annotatable::Stmt(Box::new(ecx.stmt_item(span, a)))), is_derive_const, ); } else { 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, + &item, + &mut |a| items.push(Annotatable::Item(a)), + is_derive_const, + ), + _ => unreachable!(), } ExpandResult::Ready(items) } diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs b/compiler/rustc_builtin_macros/src/deriving/ord.rs similarity index 88% rename from compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs rename to compiler/rustc_builtin_macros/src/deriving/ord.rs index a1b38ceadb228..3c2d95a299a51 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/ord.rs @@ -1,5 +1,5 @@ -use rustc_ast::{MetaItem, Safety}; -use rustc_expand::base::{Annotatable, ExtCtxt}; +use rustc_ast::Safety; +use rustc_expand::base::ExtCtxt; use rustc_span::{Ident, Span, sym}; use thin_vec::thin_vec; @@ -10,9 +10,8 @@ use crate::deriving::path_std; pub(crate) fn expand_deriving_ord( cx: &ExtCtxt<'_>, span: Span, - mitem: &MetaItem, - item: &Annotatable, - push: &mut dyn FnMut(Annotatable), + item: &ast::Item, + push: &mut dyn FnMut(Box), is_const: bool, ) { let trait_def = TraitDef { @@ -24,7 +23,7 @@ pub(crate) fn expand_deriving_ord( supports_unions: false, methods: smallvec![MethodDef { name: sym::cmp, - generics: Bounds::empty(), + generics: cx.empty_generics(span), explicit_self: true, nonself_args: smallvec![(self_ref(), sym::other)], ret_ty: Path(path_std!(cmp::Ordering)), @@ -38,10 +37,10 @@ pub(crate) fn expand_deriving_ord( document: true, }; - trait_def.expand(cx, mitem, item, push) + trait_def.expand(cx, item, push) } -pub(crate) fn cs_cmp(cx: &ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr { +pub(crate) fn cs_cmp(cx: &ExtCtxt<'_>, span: Span, substr: Substructure<'_>) -> BlockOrExpr { let test_id = Ident::new(sym::cmp, span); let equal_path = cx.path_global(span, cx.std_path(&[sym::cmp, sym::Ordering, sym::Equal])); let cmp_path = cx.std_path(&[sym::cmp, sym::Ord, sym::cmp]); 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 83% rename from compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs rename to compiler/rustc_builtin_macros/src/deriving/partial_eq.rs index b852e29b03ca4..be48c0532e596 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/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_ast::{BinOpKind, BorrowKind, Expr, ExprKind, Mutability, Safety}; +use rustc_expand::base::ExtCtxt; use rustc_span::{Span, sym}; use thin_vec::thin_vec; @@ -12,9 +12,8 @@ use crate::deriving::path_std; pub(crate) fn expand_deriving_partial_eq( cx: &ExtCtxt<'_>, span: Span, - mitem: &MetaItem, - item: &Annotatable, - push: &mut dyn FnMut(Annotatable), + item: &ast::Item, + push: &mut dyn FnMut(Box), is_const: bool, ) { let structural_trait_def = TraitDef { @@ -35,21 +34,19 @@ pub(crate) fn expand_deriving_partial_eq( safety: Safety::Default, document: true, }; - structural_trait_def.expand(cx, mitem, item, push); + structural_trait_def.expand(cx, item, push); // No need to generate `ne`, the default suffices, and not generating it is // faster. let methods = smallvec![MethodDef { name: sym::eq, - generics: Bounds::empty(), + generics: cx.empty_generics(span), explicit_self: true, nonself_args: smallvec![(self_ref(), sym::other)], 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 { @@ -65,7 +62,7 @@ pub(crate) fn expand_deriving_partial_eq( safety: Safety::Default, document: true, }; - trait_def.expand(cx, mitem, item, push) + trait_def.expand(cx, item, push) } /// Generates the equality expression for a struct or enum variant when deriving @@ -122,11 +119,11 @@ pub(crate) fn expand_deriving_partial_eq( fn get_substructure_equality_expr( cx: &ExtCtxt<'_>, span: Span, - substructure: &Substructure<'_>, -) -> Box { + substructure: Substructure<'_>, +) -> 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); @@ -143,33 +140,23 @@ fn get_substructure_equality_expr( // with logical AND. fields .iter() - .filter(|field| !field.maybe_scalar) - .fold(fields.iter().filter(|field| field.maybe_scalar).fold(None, combine), combine) + .filter(|field| field.maybe_scalar) + .chain(fields.iter().filter(|field| !field.maybe_scalar)) + .fold(None, combine) // If there are no fields, treat as always equal. .unwrap_or_else(|| cx.expr_bool(span, true)) } EnumDiscr(disc, match_expr) => { - let lhs = get_field_equality_expr(cx, disc); + 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. cx.expr_binary(disc.span, BinOpKind::And, lhs, match_expr.clone()) } - StaticEnum(..) => cx.dcx().span_bug( - span, - "unexpected static enum encountered during `derive(PartialEq)` expansion", - ), - StaticStruct(..) => cx.dcx().span_bug( - span, - "unexpected static struct encountered during `derive(PartialEq)` expansion", - ), - AllFieldlessEnum(..) => cx.dcx().span_bug( - span, - "unexpected all-fieldless enum encountered during `derive(PartialEq)` expansion", - ), - } + _ => cx.dcx().span_bug(span, "unexpected substructure in `derive(PartialEq)`"), + }) } /// Generates an equality comparison expression for a single struct or enum 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 82% rename from compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs rename to compiler/rustc_builtin_macros/src/deriving/partial_ord.rs index 88141224fddc2..fe5e48b11367d 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs @@ -1,5 +1,5 @@ -use rustc_ast::{ExprKind, ItemKind, MetaItem, PatKind, Safety, ast}; -use rustc_expand::base::{Annotatable, ExtCtxt}; +use rustc_ast::{ExprKind, ItemKind, PatKind, Safety, ast}; +use rustc_expand::base::ExtCtxt; use rustc_span::{Ident, Span, sym}; use thin_vec::thin_vec; @@ -10,9 +10,8 @@ use crate::deriving::{path_std, pathvec}; pub(crate) fn expand_deriving_partial_ord( cx: &ExtCtxt<'_>, span: Span, - mitem: &MetaItem, - item: &Annotatable, - push: &mut dyn FnMut(Annotatable), + item: &ast::Item, + push: &mut dyn FnMut(Box), is_const: bool, ) { let ordering_ty = Path(path_std!(cmp::Ordering)); @@ -20,9 +19,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,35 +46,32 @@ 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, }; let partial_cmp_def = MethodDef { name: sym::partial_cmp, - generics: Bounds::empty(), + generics: cx.empty_generics(span), explicit_self: true, nonself_args: smallvec![(self_ref(), sym::other)], ret_ty, @@ -99,7 +93,7 @@ pub(crate) fn expand_deriving_partial_ord( safety: Safety::Default, document: true, }; - trait_def.expand_ext(cx, mitem, item, push, is_simple) + trait_def.expand_ext(cx, item, push, is_simple) } // Special case for the type deriving both `PartialOrd` and `Ord`. Builds: @@ -116,7 +110,7 @@ fn cs_partial_cmp_simple(cx: &ExtCtxt<'_>, span: Span, other_expr: Box, span: Span, - substr: &Substructure<'_>, + substr: Substructure<'_>, discr_then_data: bool, ) -> BlockOrExpr { let test_id = Ident::new(sym::cmp, span); diff --git a/compiler/rustc_builtin_macros/src/deriving/reborrow.rs b/compiler/rustc_builtin_macros/src/deriving/reborrow.rs index 9dc1ccf4fd8e6..dc45b1a896bc9 100644 --- a/compiler/rustc_builtin_macros/src/deriving/reborrow.rs +++ b/compiler/rustc_builtin_macros/src/deriving/reborrow.rs @@ -1,8 +1,6 @@ -use rustc_ast::{ - self as ast, AttrArgs, GenericArg, GenericParamKind, Generics, ItemKind, MetaItem, token, -}; +use rustc_ast::{self as ast, AttrArgs, GenericArg, GenericParamKind, Generics, ItemKind, 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; @@ -14,9 +12,8 @@ macro_rules! path { pub(crate) fn expand_deriving_reborrow( cx: &ExtCtxt<'_>, span: Span, - _mitem: &MetaItem, - item: &Annotatable, - push: &mut dyn FnMut(Annotatable), + item: &ast::Item, + push: &mut dyn FnMut(Box), _is_const: bool, ) { let Some((ident, generics)) = struct_def(cx, span, item, sym::Reborrow) else { @@ -29,9 +26,8 @@ pub(crate) fn expand_deriving_reborrow( pub(crate) fn expand_deriving_coerce_shared( cx: &ExtCtxt<'_>, span: Span, - _mitem: &MetaItem, - item: &Annotatable, - push: &mut dyn FnMut(Annotatable), + item: &ast::Item, + push: &mut dyn FnMut(Box), _is_const: bool, ) { let Some((ident, generics)) = struct_def(cx, span, item, sym::CoerceShared) else { @@ -55,25 +51,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 +71,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 }); @@ -130,7 +115,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)); @@ -154,7 +139,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 { @@ -169,7 +154,7 @@ fn push_marker_impl( self_ty, items: ThinVec::new(), }), - ))); + )); } fn impl_generics(cx: &ExtCtxt<'_>, generics: &Generics) -> Generics { 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, diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index 2240fe115fde3..393acc7e2e65f 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -767,4 +767,16 @@ impl<'a> ExtCtxt<'a> { let g = &self.sess.psess.attr_id_generator; attr::mk_attr_from_item(g, inner, None, ast::AttrStyle::Outer, span) } + + pub fn empty_generics(&self, span: Span) -> ast::Generics { + ast::Generics { + params: ThinVec::new(), + where_clause: ast::WhereClause { + has_where_token: false, + predicates: ThinVec::new(), + span, + }, + span, + } + } } diff --git a/tests/ui/derives/deriving-all-codegen.stdout b/tests/ui/derives/deriving-all-codegen.stdout index 320c1b5861162..436f57bb8ecb9 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 { @@ -1009,12 +1009,7 @@ impl ::core::cmp::PartialEq for Enum0 { fn eq(&self, other: &Enum0) -> bool { match *self {} } } #[automatically_derived] -impl ::core::cmp::Eq for Enum0 { - #[inline] - #[doc(hidden)] - #[coverage(off)] - fn assert_fields_are_eq(&self) {} -} +impl ::core::cmp::Eq for Enum0 { } #[automatically_derived] impl ::core::cmp::PartialOrd for Enum0 { #[inline] @@ -1142,12 +1137,7 @@ impl ::core::cmp::PartialEq for Fieldless1 { fn eq(&self, other: &Fieldless1) -> bool { true } } #[automatically_derived] -impl ::core::cmp::Eq for Fieldless1 { - #[inline] - #[doc(hidden)] - #[coverage(off)] - fn assert_fields_are_eq(&self) {} -} +impl ::core::cmp::Eq for Fieldless1 { } #[automatically_derived] impl ::core::cmp::PartialOrd for Fieldless1 { #[inline] @@ -1219,12 +1209,7 @@ impl ::core::cmp::PartialEq for Fieldless { } } #[automatically_derived] -impl ::core::cmp::Eq for Fieldless { - #[inline] - #[doc(hidden)] - #[coverage(off)] - fn assert_fields_are_eq(&self) {} -} +impl ::core::cmp::Eq for Fieldless { } #[automatically_derived] impl ::core::cmp::PartialOrd for Fieldless { #[inline]