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