Serde, attribute macros, and the 2018 edition preview

I'm trying to port a toy codebase forward to the 2018 preview. It uses serde's awesome attribute annotations for things like field renaming and flattening. But rustc is complaining about not finding the macros.

#![feature(rust_2018_preview, use_extern_macros)]
#![allow(unknown_lints)]
#![warn(clippy)]
#![warn(rust_2018_idioms)]

use serde;
use serde_derive;
use serde_json;

#[derive(Serialize, Deserialize, Debug)]
#[serde(rename_all = "PascalCase")]
struct PropKV {
    name: String,
    value: String,
}

But I get an error:

error: cannot find attribute macro `serde` in this scope

Note that it's fine with the derive macro, but not the serde one.

I assume I need to use something else from serde that was previously implied in the #[macro_use] extern crate incantation, but I can't find what. Hints welcome!

1 Like

As described in the 2018 edition guide, macros (including derives) are now directly imported, just like anything else:

use serde_derive::{Deserialize, Serialize};
use serde_json;

#[derive(Serialize, Deserialize, Debug)]
#[serde(rename_all = "PascalCase")]
struct PropKV {
    name: String,
    value: String,
}

fn main() {
    let p = PropKV {
        name: "a".into(),
        value: "b".into(),
    };
    let s = serde_json::to_string(&p);
    println!("{:?}", s)
}

(Playground)

Output:

Ok("{\"Name\":\"a\",\"Value\":\"b\"}")

Note that it’s fine with the derive macro, but not the serde one.

It's not, really. It just hasn't gotten to that error yet.

2 Likes

Hmm. Thanks!

Yes, I read the edition guide, and that's why I have the use_extern_macros at the top. That made it stop complaining about the derives, so I thought it was fine with that. I went looking for things called serde to import, like use serde::serde or use serde_derive::serde, to get the name it was complaining about in scope.

There's clearly an opportunity for improved error messages here, though I suspect it's.. tricky.