1 use crate::deriving::generic::ty::*;
2 use crate::deriving::generic::*;
3 use crate::deriving::{path_local, path_std};
5 use rustc_ast::{BinOpKind, BorrowKind, Expr, ExprKind, MetaItem, Mutability};
6 use rustc_expand::base::{Annotatable, ExtCtxt};
7 use rustc_span::symbol::sym;
9 use thin_vec::thin_vec;
11 pub fn expand_deriving_partial_eq(
16 push: &mut dyn FnMut(Annotatable),
19 fn cs_eq(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
26 |cx, fold| match fold {
27 CsFold::Single(field) => {
28 let [other_expr] = &field.other_selflike_exprs[..] else {
29 cx.span_bug(field.span, "not exactly 2 arguments in `derive(PartialEq)`");
32 // We received `&T` arguments. Convert them to `T` by
33 // stripping `&` or adding `*`. This isn't necessary for
34 // type checking, but it results in much better error
35 // messages if something goes wrong.
36 let convert = |expr: &P<Expr>| {
37 if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner) =
42 cx.expr_deref(field.span, expr.clone())
48 convert(&field.self_expr),
52 CsFold::Combine(span, expr1, expr2) => {
53 cx.expr_binary(span, BinOpKind::And, expr1, expr2)
55 CsFold::Fieldless => cx.expr_bool(span, base),
58 BlockOrExpr::new_expr(expr)
61 super::inject_impl_of_structural_trait(
65 path_std!(marker::StructuralPartialEq),
69 // No need to generate `ne`, the default suffices, and not generating it is
71 let attrs = thin_vec![cx.attr_word(sym::inline, span)];
72 let methods = vec![MethodDef {
74 generics: Bounds::empty(),
76 nonself_args: vec![(self_ref(), sym::other)],
77 ret_ty: Path(path_local!(bool)),
79 fieldless_variants_strategy: FieldlessVariantsStrategy::Unify,
80 combine_substructure: combine_substructure(Box::new(|a, b, c| cs_eq(a, b, c))),
83 let trait_def = TraitDef {
85 path: path_std!(cmp::PartialEq),
86 skip_path_as_bound: false,
87 additional_bounds: Vec::new(),
88 supports_unions: false,
90 associated_types: Vec::new(),
93 trait_def.expand(cx, mitem, item, push)