summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_builtin_macros/src/deriving
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_builtin_macros/src/deriving')
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/bounds.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs19
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs19
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/generic/mod.rs34
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/mod.rs98
5 files changed, 50 insertions, 122 deletions
diff --git a/compiler/rustc_builtin_macros/src/deriving/bounds.rs b/compiler/rustc_builtin_macros/src/deriving/bounds.rs
index 2c8e6f99c..8027ca2e7 100644
--- a/compiler/rustc_builtin_macros/src/deriving/bounds.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/bounds.rs
@@ -41,7 +41,7 @@ pub fn expand_deriving_const_param_ty(
path: path_std!(marker::ConstParamTy),
skip_path_as_bound: false,
needs_copy_as_bound_if_packed: false,
- additional_bounds: Vec::new(),
+ additional_bounds: vec![ty::Ty::Path(path_std!(cmp::Eq))],
supports_unions: false,
methods: Vec::new(),
associated_types: Vec::new(),
diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs
index c78a0eb04..a000e4895 100644
--- a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs
@@ -18,6 +18,20 @@ pub fn expand_deriving_eq(
is_const: bool,
) {
let span = cx.with_def_site_ctxt(span);
+
+ let structural_trait_def = TraitDef {
+ span,
+ path: path_std!(marker::StructuralEq),
+ skip_path_as_bound: true, // crucial!
+ needs_copy_as_bound_if_packed: false,
+ additional_bounds: Vec::new(),
+ supports_unions: true,
+ methods: Vec::new(),
+ associated_types: Vec::new(),
+ is_const: false,
+ };
+ structural_trait_def.expand(cx, mitem, item, push);
+
let trait_def = TraitDef {
span,
path: path_std!(cmp::Eq),
@@ -34,7 +48,7 @@ pub fn expand_deriving_eq(
attributes: thin_vec![
cx.attr_word(sym::inline, span),
cx.attr_nested_word(sym::doc, sym::hidden, span),
- cx.attr_word(sym::no_coverage, span)
+ cx.attr_nested_word(sym::coverage, sym::off, span)
],
fieldless_variants_strategy: FieldlessVariantsStrategy::Unify,
combine_substructure: combine_substructure(Box::new(|a, b, c| {
@@ -44,9 +58,6 @@ pub fn expand_deriving_eq(
associated_types: Vec::new(),
is_const,
};
-
- super::inject_impl_of_structural_trait(cx, span, item, path_std!(marker::StructuralEq), push);
-
trait_def.expand_ext(cx, mitem, item, push, true)
}
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 a71ecc5db..a170468b4 100644
--- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs
@@ -72,13 +72,20 @@ pub fn expand_deriving_partial_eq(
BlockOrExpr::new_expr(expr)
}
- super::inject_impl_of_structural_trait(
- cx,
+ let structural_trait_def = TraitDef {
span,
- item,
- path_std!(marker::StructuralPartialEq),
- push,
- );
+ path: path_std!(marker::StructuralPartialEq),
+ skip_path_as_bound: true, // crucial!
+ needs_copy_as_bound_if_packed: false,
+ additional_bounds: Vec::new(),
+ // We really don't support unions, but that's already checked by the impl generated below;
+ // a second check here would lead to redundant error messages.
+ supports_unions: true,
+ methods: Vec::new(),
+ associated_types: Vec::new(),
+ is_const: false,
+ };
+ structural_trait_def.expand(cx, mitem, item, push);
// No need to generate `ne`, the default suffices, and not generating it is
// faster.
diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
index 6597ee3cf..7252658d4 100644
--- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
@@ -88,7 +88,7 @@
//!
//! When generating the `expr` for the `A` impl, the `SubstructureFields` is
//!
-//! ```{.text}
+//! ```text
//! Struct(vec![FieldInfo {
//! span: <span of x>
//! name: Some(<ident of x>),
@@ -99,7 +99,7 @@
//!
//! For the `B` impl, called with `B(a)` and `B(b)`,
//!
-//! ```{.text}
+//! ```text
//! Struct(vec![FieldInfo {
//! span: <span of `i32`>,
//! name: None,
@@ -113,7 +113,7 @@
//! When generating the `expr` for a call with `self == C0(a)` and `other
//! == C0(b)`, the SubstructureFields is
//!
-//! ```{.text}
+//! ```text
//! EnumMatching(0, <ast::Variant for C0>,
//! vec![FieldInfo {
//! span: <span of i32>
@@ -125,7 +125,7 @@
//!
//! For `C1 {x}` and `C1 {x}`,
//!
-//! ```{.text}
+//! ```text
//! EnumMatching(1, <ast::Variant for C1>,
//! vec![FieldInfo {
//! span: <span of x>
@@ -137,7 +137,7 @@
//!
//! For the tags,
//!
-//! ```{.text}
+//! ```text
//! EnumTag(
//! &[<ident of self tag>, <ident of other tag>], <expr to combine with>)
//! ```
@@ -149,7 +149,7 @@
//!
//! A static method on the types above would result in,
//!
-//! ```{.text}
+//! ```text
//! StaticStruct(<ast::VariantData of A>, Named(vec![(<ident of x>, <span of x>)]))
//!
//! StaticStruct(<ast::VariantData of B>, Unnamed(vec![<span of x>]))
@@ -711,7 +711,9 @@ impl<'a> TraitDef<'a> {
.collect();
// Require the current trait.
- bounds.push(cx.trait_bound(trait_path.clone(), self.is_const));
+ if !self.skip_path_as_bound {
+ bounds.push(cx.trait_bound(trait_path.clone(), self.is_const));
+ }
// Add a `Copy` bound if required.
if is_packed && self.needs_copy_as_bound_if_packed {
@@ -722,15 +724,17 @@ impl<'a> TraitDef<'a> {
));
}
- let predicate = ast::WhereBoundPredicate {
- span: self.span,
- bound_generic_params: field_ty_param.bound_generic_params,
- bounded_ty: field_ty_param.ty,
- bounds,
- };
+ if !bounds.is_empty() {
+ let predicate = ast::WhereBoundPredicate {
+ span: self.span,
+ bound_generic_params: field_ty_param.bound_generic_params,
+ bounded_ty: field_ty_param.ty,
+ bounds,
+ };
- let predicate = ast::WherePredicate::BoundPredicate(predicate);
- where_clause.predicates.push(predicate);
+ let predicate = ast::WherePredicate::BoundPredicate(predicate);
+ where_clause.predicates.push(predicate);
+ }
}
}
}
diff --git a/compiler/rustc_builtin_macros/src/deriving/mod.rs b/compiler/rustc_builtin_macros/src/deriving/mod.rs
index d34336e76..a6f3252e7 100644
--- a/compiler/rustc_builtin_macros/src/deriving/mod.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/mod.rs
@@ -2,9 +2,9 @@
use rustc_ast as ast;
use rustc_ast::ptr::P;
-use rustc_ast::{GenericArg, Impl, ItemKind, MetaItem};
+use rustc_ast::{GenericArg, MetaItem};
use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, MultiItemModifier};
-use rustc_span::symbol::{sym, Ident, Symbol};
+use rustc_span::symbol::{sym, Symbol};
use rustc_span::Span;
use thin_vec::{thin_vec, ThinVec};
@@ -116,100 +116,6 @@ fn call_unreachable(cx: &ExtCtxt<'_>, span: Span) -> P<ast::Expr> {
}))
}
-// Injects `impl<...> Structural for ItemType<...> { }`. In particular,
-// does *not* add `where T: Structural` for parameters `T` in `...`.
-// (That's the main reason we cannot use TraitDef here.)
-fn inject_impl_of_structural_trait(
- cx: &mut ExtCtxt<'_>,
- span: Span,
- item: &Annotatable,
- structural_path: generic::ty::Path,
- push: &mut dyn FnMut(Annotatable),
-) {
- let Annotatable::Item(item) = item else {
- unreachable!();
- };
-
- let generics = match &item.kind {
- ItemKind::Struct(_, generics) | ItemKind::Enum(_, generics) => generics,
- // Do not inject `impl Structural for Union`. (`PartialEq` does not
- // support unions, so we will see error downstream.)
- ItemKind::Union(..) => return,
- _ => unreachable!(),
- };
-
- // Create generics param list for where clauses and impl headers
- let mut generics = generics.clone();
-
- let ctxt = span.ctxt();
-
- // Create the type of `self`.
- //
- // in addition, remove defaults from generic params (impls cannot have them).
- let self_params: Vec<_> = generics
- .params
- .iter_mut()
- .map(|param| match &mut param.kind {
- ast::GenericParamKind::Lifetime => ast::GenericArg::Lifetime(
- cx.lifetime(param.ident.span.with_ctxt(ctxt), param.ident),
- ),
- ast::GenericParamKind::Type { default } => {
- *default = None;
- ast::GenericArg::Type(cx.ty_ident(param.ident.span.with_ctxt(ctxt), param.ident))
- }
- ast::GenericParamKind::Const { ty: _, kw_span: _, default } => {
- *default = None;
- ast::GenericArg::Const(
- cx.const_ident(param.ident.span.with_ctxt(ctxt), param.ident),
- )
- }
- })
- .collect();
-
- let type_ident = item.ident;
-
- let trait_ref = cx.trait_ref(structural_path.to_path(cx, span, type_ident, &generics));
- let self_type = cx.ty_path(cx.path_all(span, false, vec![type_ident], self_params));
-
- // It would be nice to also encode constraint `where Self: Eq` (by adding it
- // onto `generics` cloned above). Unfortunately, that strategy runs afoul of
- // rust-lang/rust#48214. So we perform that additional check in the compiler
- // itself, instead of encoding it here.
-
- // Keep the lint and stability attributes of the original item, to control
- // how the generated implementation is linted.
- let mut attrs = ast::AttrVec::new();
- attrs.extend(
- item.attrs
- .iter()
- .filter(|a| {
- [sym::allow, sym::warn, sym::deny, sym::forbid, sym::stable, sym::unstable]
- .contains(&a.name_or_empty())
- })
- .cloned(),
- );
- // Mark as `automatically_derived` to avoid some silly lints.
- attrs.push(cx.attr_word(sym::automatically_derived, span));
-
- let newitem = cx.item(
- span,
- Ident::empty(),
- attrs,
- ItemKind::Impl(Box::new(Impl {
- unsafety: ast::Unsafe::No,
- polarity: ast::ImplPolarity::Positive,
- defaultness: ast::Defaultness::Final,
- constness: ast::Const::No,
- generics,
- of_trait: Some(trait_ref),
- self_ty: self_type,
- items: ThinVec::new(),
- })),
- );
-
- push(Annotatable::Item(newitem));
-}
-
fn assert_ty_bounds(
cx: &mut ExtCtxt<'_>,
stmts: &mut ThinVec<ast::Stmt>,