]>
Commit | Line | Data |
---|---|---|
9fa01778 | 1 | use crate::deriving::generic::ty::*; |
dfeec247 XL |
2 | use crate::deriving::generic::*; |
3 | use crate::deriving::path_std; | |
9cc50fc6 | 4 | |
74b04a01 | 5 | use rustc_ast::ptr::P; |
3dfed10e | 6 | use rustc_ast::{self as ast, Expr, GenericArg, MetaItem}; |
dfeec247 | 7 | use rustc_expand::base::{Annotatable, ExtCtxt}; |
f9f354fc | 8 | use rustc_span::symbol::{sym, Ident, Symbol}; |
dfeec247 | 9 | use rustc_span::Span; |
970d7e83 | 10 | |
dfeec247 XL |
11 | pub fn expand_deriving_eq( |
12 | cx: &mut ExtCtxt<'_>, | |
13 | span: Span, | |
14 | mitem: &MetaItem, | |
15 | item: &Annotatable, | |
16 | push: &mut dyn FnMut(Annotatable), | |
17 | ) { | |
cdc7bbd5 | 18 | let span = cx.with_def_site_ctxt(span); |
dc9dc135 | 19 | let inline = cx.meta_word(span, sym::inline); |
74b04a01 XL |
20 | let hidden = rustc_ast::attr::mk_nested_word_item(Ident::new(sym::hidden, span)); |
21 | let doc = rustc_ast::attr::mk_list_item(Ident::new(sym::doc, span), vec![hidden]); | |
cdc7bbd5 XL |
22 | let no_coverage = cx.meta_word(span, sym::no_coverage); |
23 | let attrs = vec![cx.attribute(inline), cx.attribute(doc), cx.attribute(no_coverage)]; | |
d9579d0f | 24 | let trait_def = TraitDef { |
3b2f2976 | 25 | span, |
d9579d0f | 26 | attributes: Vec::new(), |
3dfed10e | 27 | path: path_std!(cmp::Eq), |
d9579d0f | 28 | additional_bounds: Vec::new(), |
3dfed10e | 29 | generics: Bounds::empty(), |
e9174d1e | 30 | is_unsafe: false, |
9e0c209e | 31 | supports_unions: true, |
5bcae85e | 32 | methods: vec![MethodDef { |
3dfed10e XL |
33 | name: sym::assert_receiver_is_total_eq, |
34 | generics: Bounds::empty(), | |
dfeec247 XL |
35 | explicit_self: borrowed_explicit_self(), |
36 | args: vec![], | |
37 | ret_ty: nil_ty(), | |
38 | attributes: attrs, | |
39 | is_unsafe: false, | |
40 | unify_fieldless_variants: true, | |
41 | combine_substructure: combine_substructure(Box::new(|a, b, c| { | |
42 | cs_total_eq_assert(a, b, c) | |
43 | })), | |
44 | }], | |
85aaf69f | 45 | associated_types: Vec::new(), |
970d7e83 | 46 | }; |
e74abb32 | 47 | |
3dfed10e | 48 | super::inject_impl_of_structural_trait(cx, span, item, path_std!(marker::StructuralEq), push); |
e74abb32 | 49 | |
9e0c209e SL |
50 | trait_def.expand_ext(cx, mitem, item, push, true) |
51 | } | |
52 | ||
dfeec247 XL |
53 | fn cs_total_eq_assert( |
54 | cx: &mut ExtCtxt<'_>, | |
55 | trait_span: Span, | |
56 | substr: &Substructure<'_>, | |
57 | ) -> P<Expr> { | |
58 | fn assert_ty_bounds( | |
59 | cx: &mut ExtCtxt<'_>, | |
60 | stmts: &mut Vec<ast::Stmt>, | |
61 | ty: P<ast::Ty>, | |
62 | span: Span, | |
63 | helper_name: &str, | |
64 | ) { | |
9e0c209e SL |
65 | // Generate statement `let _: helper_name<ty>;`, |
66 | // set the expn ID so we can use the unstable struct. | |
e1599b0c | 67 | let span = cx.with_def_site_ctxt(span); |
dfeec247 XL |
68 | let assert_path = cx.path_all( |
69 | span, | |
70 | true, | |
71 | cx.std_path(&[sym::cmp, Symbol::intern(helper_name)]), | |
72 | vec![GenericArg::Type(ty)], | |
73 | ); | |
9e0c209e SL |
74 | stmts.push(cx.stmt_let_type_only(span, cx.ty_path(assert_path))); |
75 | } | |
dfeec247 XL |
76 | fn process_variant( |
77 | cx: &mut ExtCtxt<'_>, | |
78 | stmts: &mut Vec<ast::Stmt>, | |
79 | variant: &ast::VariantData, | |
80 | ) { | |
9e0c209e SL |
81 | for field in variant.fields() { |
82 | // let _: AssertParamIsEq<FieldTy>; | |
83 | assert_ty_bounds(cx, stmts, field.ty.clone(), field.span, "AssertParamIsEq"); | |
84 | } | |
85 | } | |
86 | ||
87 | let mut stmts = Vec::new(); | |
88 | match *substr.fields { | |
89 | StaticStruct(vdata, ..) => { | |
90 | process_variant(cx, &mut stmts, vdata); | |
91 | } | |
92 | StaticEnum(enum_def, ..) => { | |
93 | for variant in &enum_def.variants { | |
e1599b0c | 94 | process_variant(cx, &mut stmts, &variant.data); |
9e0c209e SL |
95 | } |
96 | } | |
dfeec247 | 97 | _ => cx.span_bug(trait_span, "unexpected substructure in `derive(Eq)`"), |
9e0c209e SL |
98 | } |
99 | cx.expr_block(cx.block(trait_span, stmts)) | |
970d7e83 | 100 | } |