[Before reading all this, please keep at the front of your find that there are rewriters and derivers. A deriver is a plugin to the @@deriving
rewriter.]
Remember that @@deriving
is an attribute. The fact that it has a payload is a matter for the PPX rewriter that processes it. The only thing that the infrastructure (either pa_ppx
or ppxlib
) does, is to decide whether any particular instance of an attribute, should be handled by some particular rewriter it has loaded. So in your example, there are three instances of @@deriving
. They’re going to be handed-off by pa_ppx
/ppxlib
to some code, and that’s going to happen without looking at the payload, right? Or at least, that’s how I implemented it. Then, the code for @@deriving
will look at the payload and figure out which derivers to invoke.
So either pa_ppx
has loaded a PPX rewriter for @@deriving
, or it has not. If it has, then that rewriter is going to try to process these attributes. If no such rewriter has been loaded, then these attributes will be passed unmodified to ppxlib
, and if ppxlib
has loaded a rewriter for @@deriving
, then that rewriter can process these attributes.
From this, you can see that if both infrastructures load rewriters, then the first one (pa_ppx
) gets a crack, and however it processes the attribute, is how it will be processed.
BTW, my understanding of the spec for @@deriving
is that when you have an attribute
type t = ... [@@deriving a,b]
then it’s supposed to be expanded to
.... code generated by the deriver ...
[@@@end]
Or at least, that’s how I remember it. And it’s how I implemented it. I have a vague memory that ppxlib`` does not implement this "rewrite the attribute" (notice the "_inline") but maybe it does -- I rarely use or look at
ppxlib` rewriters/derivers except when I’m doing compatibility testing.
In any case, if this is the way things are supposed to be expanded, then clearly, only one @@deriving
rewriter can get a whack at the @@deriving
attribute.