1 //! The compiler code necessary to implement the `#[derive]` extensions.
3 use syntax
::ast
::{self, ItemKind, MetaItem}
;
4 use syntax_expand
::base
::{Annotatable, ExtCtxt, MultiItemModifier}
;
6 use syntax
::symbol
::{Symbol, sym}
;
9 macro path_local($x
:ident
) {
10 generic
::ty
::Path
::new_local(stringify
!($x
))
13 macro pathvec_std($cx
:expr
, $
($rest
:ident
)::+) {{
14 vec
![ $
( stringify
!($rest
) ),+ ]
17 macro path_std($
($x
:tt
)*) {
18 generic
::ty
::Path
::new( pathvec_std
!( $
($x
)* ) )
29 #[path="cmp/partial_eq.rs"]
33 #[path="cmp/partial_ord.rs"]
40 crate struct BuiltinDerive(
41 crate fn(&mut ExtCtxt
<'_
>, Span
, &MetaItem
, &Annotatable
, &mut dyn FnMut(Annotatable
))
44 impl MultiItemModifier
for BuiltinDerive
{
46 ecx
: &mut ExtCtxt
<'_
>,
51 // FIXME: Built-in derives often forget to give spans contexts,
52 // so we are doing it here in a centralized way.
53 let span
= ecx
.with_def_site_ctxt(span
);
54 let mut items
= Vec
::new();
55 (self.0)(ecx
, span
, meta_item
, &item
, &mut |a
| items
.push(a
));
60 /// Constructs an expression that calls an intrinsic
61 fn call_intrinsic(cx
: &ExtCtxt
<'_
>,
64 args
: Vec
<P
<ast
::Expr
>>)
66 let span
= cx
.with_def_site_ctxt(span
);
67 let path
= cx
.std_path(&[sym
::intrinsics
, Symbol
::intern(intrinsic
)]);
68 let call
= cx
.expr_call_global(span
, path
, args
);
70 cx
.expr_block(P(ast
::Block
{
71 stmts
: vec
![cx
.stmt_expr(call
)],
72 id
: ast
::DUMMY_NODE_ID
,
73 rules
: ast
::BlockCheckMode
::Unsafe(ast
::CompilerGenerated
),
79 // Injects `impl<...> Structural for ItemType<...> { }`. In particular,
80 // does *not* add `where T: Structural` for parameters `T` in `...`.
81 // (That's the main reason we cannot use TraitDef here.)
82 fn inject_impl_of_structural_trait(cx
: &mut ExtCtxt
<'_
>,
85 structural_path
: generic
::ty
::Path
<'_
>,
86 push
: &mut dyn FnMut(Annotatable
)) {
87 let item
= match *item
{
88 Annotatable
::Item(ref item
) => item
,
90 // Non-Item derive is an error, but it should have been
92 // libsyntax/ext/expand.rs:MacroExpander::expand()
97 let generics
= match item
.kind
{
98 ItemKind
::Struct(_
, ref generics
) |
99 ItemKind
::Enum(_
, ref generics
) => generics
,
100 // Do not inject `impl Structural for Union`. (`PartialEq` does not
101 // support unions, so we will see error downstream.)
102 ItemKind
::Union(..) => return,
106 // Create generics param list for where clauses and impl headers
107 let mut generics
= generics
.clone();
109 // Create the type of `self`.
111 // in addition, remove defaults from type params (impls cannot have them).
112 let self_params
: Vec
<_
> = generics
.params
.iter_mut().map(|param
| match &mut param
.kind
{
113 ast
::GenericParamKind
::Lifetime
=> {
114 ast
::GenericArg
::Lifetime(cx
.lifetime(span
, param
.ident
))
116 ast
::GenericParamKind
::Type { default }
=> {
118 ast
::GenericArg
::Type(cx
.ty_ident(span
, param
.ident
))
120 ast
::GenericParamKind
::Const { ty: _ }
=> {
121 ast
::GenericArg
::Const(cx
.const_ident(span
, param
.ident
))
125 let type_ident
= item
.ident
;
127 let trait_ref
= cx
.trait_ref(structural_path
.to_path(cx
, span
, type_ident
, &generics
));
128 let self_type
= cx
.ty_path(cx
.path_all(span
, false, vec
![type_ident
], self_params
));
130 // It would be nice to also encode constraint `where Self: Eq` (by adding it
131 // onto `generics` cloned above). Unfortunately, that strategy runs afoul of
132 // rust-lang/rust#48214. So we perform that additional check in the compiler
133 // itself, instead of encoding it here.
135 // Keep the lint and stability attributes of the original item, to control
136 // how the generated implementation is linted.
137 let mut attrs
= Vec
::new();
138 attrs
.extend(item
.attrs
141 [sym
::allow
, sym
::warn
, sym
::deny
, sym
::forbid
, sym
::stable
, sym
::unstable
]
142 .contains(&a
.name_or_empty())
146 let newitem
= cx
.item(span
,
147 ast
::Ident
::invalid(),
149 ItemKind
::Impl(ast
::Unsafety
::Normal
,
150 ast
::ImplPolarity
::Positive
,
151 ast
::Defaultness
::Final
,
157 push(Annotatable
::Item(newitem
));