Facilitating the spread of knowledge and innovation in professional software development



Choose your language

InfoQ Homepage News Rust 1.30 Brings More Metaprogramming Support and Improved Modules

Rust 1.30 Brings More Metaprogramming Support and Improved Modules

This item in japanese


The latest release of Rust, version 1.30 extends procedural macros by allowing them to define new attributes and function-like macros. Additionally, it streamlines the Rust module system by making it more consistent and straightforward.

Rust 1.30 introduces two new types of procedural macros, "attribute-like procedural macros" and "function-like procedural macros". Procedural macros are Rust metaprogramming foundation and enable the manipulation of a program syntax tree. In this respect procedural macros are much more powerful than declarative macros, which provide a mechanism to define a shorthand for more complex code based on pattern matching.

Attribute-like procedural macros are similar to existing derive macros but are more flexible in that they allow you to create new attributes and may be applied also to functions in addition to structs and enums. For example, an attribute macro could enable the specification of a route attribute to define HTTP routing:

// use of route procedural macro
#[route(GET, "/")]
fn index() {

// procedural macro defining route
pub fn route(attr: TokenStream, item: TokenStream) -> TokenStream {
  // attr receives the GET, "/" part of the macro
  // item receives fn index () { ...

Similarly, function-like procedural macros allows you to define macros that look like functions, e.g.:

// parse an SQL statement
let sql = sql!(SELECT * FROM posts WHERE id=1);

pub fn sql(input: TokenStream) -> TokenStream {

In both examples, TokenStream represents the syntax tree the attribute is applied to or the attribute/function definition. The route/sql function converts the received syntax tree into a new syntax tree which is returned to the caller, i.e., generating new code to execute.

Rust 1.30 also brings a few changes to the use macro to improve developer experience when using Rust module system. Firstly, use can now bring in a macro definition, thus making the macro_use annotation obsolete:

// old:
extern crate serde_json;

// new:
extern crate serde_json;
use serde_json::json;

Additionally, external crates are now more resilient to functions being moved across the module hierarchy by ensuring all references to a namespace are checked against all extern crate directives included in the module prelude and using the one that matches, if any. Previously, you had to explicitly use extern inside of a module or use the ::extern_name syntax, as shown in the following example:

extern crate serde_json;

fn main() {
    let json = serde_json::from_str("..."); // OK

mod foo {

    // to use serde_json in this module you explicitly use it
    use serde_json;

    fn bar() {
        let json = serde_json::from_str("...");

    fn baz() {
      // alternatively, you fully qualify the external module name
      let json = ::serde_json::from_str("...");

Finally, use is now more consistent in the way it interprets module paths. You can use now the crate keyword to indicate that you would like the module path to start at your crate root. Previous to 1.30, this was the default for module paths but paths referring to items directly would start at the local path:

mod foo {
    pub fn bar() {
        // ...

mod baz {
    pub fn qux() {
        // old
        // does not work, which is different than with `use`:
        // foo::bar();

        // new

More changes brought by Rust 1.30 are the following:

  • You can now use keywords as identifiers by prefixing them with r#, e.g. r#for. This change is mostly motivated by the fact that Rust 2018 will introduce new keywords, so a mechanism shall be available to convert existing code using those keywords as variable or function names.
  • It is now possible to build applications not using the standard library with no_std. Previously, you could only build libraries with no_std due to the impossibility of defining a panic handler.

You can update your Rust distribution using $ rustup update stable. For full detail of Rust 1.30 do not miss the release notes.

We need your feedback

How might we improve InfoQ for you

Thank you for being an InfoQ reader.

Each year, we seek feedback from our readers to help us improve InfoQ. Would you mind spending 2 minutes to share your feedback in our short survey? Your feedback will directly help us continually evolve how we support you.

Take the Survey

Rate this Article


Hello stranger!

You need to Register an InfoQ account or or login to post comments. But there's so much more behind being registered.

Get the most out of the InfoQ experience.

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Community comments

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p


Is your profile up-to-date? Please take a moment to review and update.

Note: If updating/changing your email, a validation request will be sent

Company name:
Company role:
Company size:
You will be sent an email to validate the new email address. This pop-up will close itself in a few moments.