Quick and dirty checklist to update syn 0.11.x to syn 0.12

- Tags: gnome, rust

Today I ported gnome-class from version 0.11 of the syn crate to version 0.12. syn is a somewhat esoteric crate that you use to parse Rust code... from a stream of tokens... from within the implementation of a procedural macro. Gnome-class implements a mini-language inside your own Rust code, and so it needs to parse Rust!

The API of syn has changed a lot, which is kind of a pain in the ass — but the new API seems on the road to stabilization, and is nicer indeed.

Here is a quick list of things I had to change in gnome-class to upgrade its version of syn.

There is no extern crate synom anymore. You can use syn::synom now.

extern crate synom;    ->   use syn::synom;

SynomBuffer is now TokenBuffer:

synom::SynomBuffer  ->  syn::buffer:TokenBuffer

PResult, the result of Synom::parse(), now has the tuple's arguments reversed:

- pub type PResult<'a, O> = Result<(Cursor<'a>, O), ParseError>;
+ pub type PResult<'a, O> = Result<(O, Cursor<'a>), ParseError>;

// therefore:

impl Synom for MyThing { ... }

let x = MyThing::parse(...).unwrap().1;   ->  let x = MyThing::parse(...).unwrap().0;

The language tokens like synom::tokens::Amp, and keywords like synom::tokens::Type, are easier to use now. There is a Token! macro which you can use in type definitions, instead of having to remember the particular name of each token type:

synom::tokens::Amp  ->  Token!(&)

synom::tokens::For  ->  Token!(for)

And for the corresponding values when matching:

syn!(tokens::Colon)  ->  punct!(:)

syn!(tokens::Type)   ->  keyword!(type)

And to instantiate them for quoting/spanning:

-     tokens::Comma::default().to_tokens(tokens);
+     Token!(,)([Span::def_site()]).to_tokens(tokens);

(OK, that one wasn't nicer after all.)

To the get string for an Ident:

ident.sym.as_str()  ->  ident.as_ref()

There is no Delimited anymore; instead there is a Punctuated struct. My diff has this:

-  inputs: parens!(call!(Delimited::<MyThing, tokens::Comma>::parse_terminated)) >>
+  inputs: parens!(syn!(Punctuated<MyThing, Token!(,)>)) >>

There is no syn::Mutability anymore; now it's an Option<token>, so basically

syn::Mutability  ->  Option<Token![mut]>

which I guess lets you refer to the span of the original mut token if you need.

Some things changed names:

TypeTup { tys, .. }  ->  TypeTuple { elems, .. }

PatIdent {                          ->  PatIdent {
    mode: BindingMode(Mutability)           by_ref: Option<Token!(ref)>,
                                            mutability: Option<Token![mut]>,
    ident: Ident,                           ident: Ident,
    subpat: ...,                            subpat: Option<(Token![@], Box<Pat>)>,
    at_token: ...,                      }

TypeParen.ty  ->  TypeParen.elem   (and others like this, too)

(I don't know everything that changed names; gnome-class doesn't use all the syn types yet; these are just the ones I've run into.)

This new syn is much better at acknowledging the fine points of macro hygiene. The examples directory is particularly instructive; it shows how to properly span generated code vs. original code, so compiler error messages are nice. I need to write something about macro hygiene at some point.