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),
18 fn cs_eq(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
25 |cx, fold| match fold {
26 CsFold::Single(field) => {
27 let [other_expr] = &field.other_selflike_exprs[..] else {
28 cx.span_bug(field.span, "not exactly 2 arguments in `derive(PartialEq)`");
31 // We received `&T` arguments. Convert them to `T` by
32 // stripping `&` or adding `*`. This isn't necessary for
33 // type checking, but it results in much better error
34 // messages if something goes wrong.
35 let convert = |expr: &P<Expr>| {
36 if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner) =
41 cx.expr_deref(field.span, expr.clone())
47 convert(&field.self_expr),
51 CsFold::Combine(span, expr1, expr2) => {
52 cx.expr_binary(span, BinOpKind::And, expr1, expr2)
54 CsFold::Fieldless => cx.expr_bool(span, base),
57 BlockOrExpr::new_expr(expr)
60 super::inject_impl_of_structural_trait(
64 path_std!(marker::StructuralPartialEq),
68 // No need to generate `ne`, the default suffices, and not generating it is
70 let inline = cx.meta_word(span, sym::inline);
71 let attrs = thin_vec![cx.attribute(inline)];
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 unify_fieldless_variants: true,
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(),
92 trait_def.expand(cx, mitem, item, push)