<!DOCTYPE HTML> <html lang="en" class="sidebar-visible no-js"> <head> <!-- Book generated using mdBook --> <meta charset="UTF-8"> <title>D - Macros - The Rust Programming Language</title> <meta content="text/html; charset=utf-8" http-equiv="Content-Type"> <meta name="description" content=""> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="theme-color" content="#ffffff" /> <base href=""> <link rel="stylesheet" href="book.css"> <link href="https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800" rel="stylesheet" type="text/css"> <link href="https://fonts.googleapis.com/css?family=Source+Code+Pro:500" rel="stylesheet" type="text/css"> <link rel="shortcut icon" href="favicon.png"> <!-- Font Awesome --> <link rel="stylesheet" href="_FontAwesome/css/font-awesome.css"> <link rel="stylesheet" href="highlight.css"> <link rel="stylesheet" href="tomorrow-night.css"> <link rel="stylesheet" href="ayu-highlight.css"> <!-- Custom theme stylesheets --> </head> <body class="light"> <!-- Work around some values being stored in localStorage wrapped in quotes --> <script type="text/javascript"> try { var theme = localStorage.getItem('mdbook-theme'); var sidebar = localStorage.getItem('mdbook-sidebar'); if (theme.startsWith('"') && theme.endsWith('"')) { localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1)); } if (sidebar.startsWith('"') && sidebar.endsWith('"')) { localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1)); } } catch (e) { } </script> <!-- Set the theme before any content is loaded, prevents flash --> <script type="text/javascript"> var theme; try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { } if (theme === null || theme === undefined) { theme = 'light'; } document.body.className = theme; document.querySelector('html').className = theme + ' js'; </script> <!-- Hide / unhide sidebar before it is displayed --> <script type="text/javascript"> var html = document.querySelector('html'); var sidebar = 'hidden'; if (document.body.clientWidth >= 1080) { try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { } sidebar = sidebar || 'visible'; } html.classList.remove('sidebar-visible'); html.classList.add("sidebar-" + sidebar); </script> <nav id="sidebar" class="sidebar" aria-label="Table of contents"> <ol class="chapter"><li class="affix"><a href="foreword.html">Foreword</a></li><li class="affix"><a href="ch00-00-introduction.html">Introduction</a></li><li><a href="ch01-00-getting-started.html"><strong aria-hidden="true">1.</strong> Getting Started</a></li><li><ol class="section"><li><a href="ch01-01-installation.html"><strong aria-hidden="true">1.1.</strong> Installation</a></li><li><a href="ch01-02-hello-world.html"><strong aria-hidden="true">1.2.</strong> Hello, World!</a></li><li><a href="ch01-03-hello-cargo.html"><strong aria-hidden="true">1.3.</strong> Hello, Cargo!</a></li></ol></li><li><a href="ch02-00-guessing-game-tutorial.html"><strong aria-hidden="true">2.</strong> Programming a Guessing Game</a></li><li><a href="ch03-00-common-programming-concepts.html"><strong aria-hidden="true">3.</strong> Common Programming Concepts</a></li><li><ol class="section"><li><a href="ch03-01-variables-and-mutability.html"><strong aria-hidden="true">3.1.</strong> Variables and Mutability</a></li><li><a href="ch03-02-data-types.html"><strong aria-hidden="true">3.2.</strong> Data Types</a></li><li><a href="ch03-03-how-functions-work.html"><strong aria-hidden="true">3.3.</strong> How Functions Work</a></li><li><a href="ch03-04-comments.html"><strong aria-hidden="true">3.4.</strong> Comments</a></li><li><a href="ch03-05-control-flow.html"><strong aria-hidden="true">3.5.</strong> Control Flow</a></li></ol></li><li><a href="ch04-00-understanding-ownership.html"><strong aria-hidden="true">4.</strong> Understanding Ownership</a></li><li><ol class="section"><li><a href="ch04-01-what-is-ownership.html"><strong aria-hidden="true">4.1.</strong> What is Ownership?</a></li><li><a href="ch04-02-references-and-borrowing.html"><strong aria-hidden="true">4.2.</strong> References & Borrowing</a></li><li><a href="ch04-03-slices.html"><strong aria-hidden="true">4.3.</strong> Slices</a></li></ol></li><li><a href="ch05-00-structs.html"><strong aria-hidden="true">5.</strong> Using Structs to Structure Related Data</a></li><li><ol class="section"><li><a href="ch05-01-defining-structs.html"><strong aria-hidden="true">5.1.</strong> Defining and Instantiating Structs</a></li><li><a href="ch05-02-example-structs.html"><strong aria-hidden="true">5.2.</strong> An Example Program Using Structs</a></li><li><a href="ch05-03-method-syntax.html"><strong aria-hidden="true">5.3.</strong> Method Syntax</a></li></ol></li><li><a href="ch06-00-enums.html"><strong aria-hidden="true">6.</strong> Enums and Pattern Matching</a></li><li><ol class="section"><li><a href="ch06-01-defining-an-enum.html"><strong aria-hidden="true">6.1.</strong> Defining an Enum</a></li><li><a href="ch06-02-match.html"><strong aria-hidden="true">6.2.</strong> The match Control Flow Operator</a></li><li><a href="ch06-03-if-let.html"><strong aria-hidden="true">6.3.</strong> Concise Control Flow with if let</a></li></ol></li><li><a href="ch07-00-modules.html"><strong aria-hidden="true">7.</strong> Modules</a></li><li><ol class="section"><li><a href="ch07-01-mod-and-the-filesystem.html"><strong aria-hidden="true">7.1.</strong> mod and the Filesystem</a></li><li><a href="ch07-02-controlling-visibility-with-pub.html"><strong aria-hidden="true">7.2.</strong> Controlling Visibility with pub</a></li><li><a href="ch07-03-importing-names-with-use.html"><strong aria-hidden="true">7.3.</strong> Referring to Names in Different Modules</a></li></ol></li><li><a href="ch08-00-common-collections.html"><strong aria-hidden="true">8.</strong> Common Collections</a></li><li><ol class="section"><li><a href="ch08-01-vectors.html"><strong aria-hidden="true">8.1.</strong> Vectors</a></li><li><a href="ch08-02-strings.html"><strong aria-hidden="true">8.2.</strong> Strings</a></li><li><a href="ch08-03-hash-maps.html"><strong aria-hidden="true">8.3.</strong> Hash Maps</a></li></ol></li><li><a href="ch09-00-error-handling.html"><strong aria-hidden="true">9.</strong> Error Handling</a></li><li><ol class="section"><li><a href="ch09-01-unrecoverable-errors-with-panic.html"><strong aria-hidden="true">9.1.</strong> Unrecoverable Errors with panic!</a></li><li><a href="ch09-02-recoverable-errors-with-result.html"><strong aria-hidden="true">9.2.</strong> Recoverable Errors with Result</a></li><li><a href="ch09-03-to-panic-or-not-to-panic.html"><strong aria-hidden="true">9.3.</strong> To panic! or Not To panic!</a></li></ol></li><li><a href="ch10-00-generics.html"><strong aria-hidden="true">10.</strong> Generic Types, Traits, and Lifetimes</a></li><li><ol class="section"><li><a href="ch10-01-syntax.html"><strong aria-hidden="true">10.1.</strong> Generic Data Types</a></li><li><a href="ch10-02-traits.html"><strong aria-hidden="true">10.2.</strong> Traits: Defining Shared Behavior</a></li><li><a href="ch10-03-lifetime-syntax.html"><strong aria-hidden="true">10.3.</strong> Validating References with Lifetimes</a></li></ol></li><li><a href="ch11-00-testing.html"><strong aria-hidden="true">11.</strong> Testing</a></li><li><ol class="section"><li><a href="ch11-01-writing-tests.html"><strong aria-hidden="true">11.1.</strong> Writing tests</a></li><li><a href="ch11-02-running-tests.html"><strong aria-hidden="true">11.2.</strong> Running tests</a></li><li><a href="ch11-03-test-organization.html"><strong aria-hidden="true">11.3.</strong> Test Organization</a></li></ol></li><li><a href="ch12-00-an-io-project.html"><strong aria-hidden="true">12.</strong> An I/O Project: Building a Command Line Program</a></li><li><ol class="section"><li><a href="ch12-01-accepting-command-line-arguments.html"><strong aria-hidden="true">12.1.</strong> Accepting Command Line Arguments</a></li><li><a href="ch12-02-reading-a-file.html"><strong aria-hidden="true">12.2.</strong> Reading a File</a></li><li><a href="ch12-03-improving-error-handling-and-modularity.html"><strong aria-hidden="true">12.3.</strong> Refactoring to Improve Modularity and Error Handling</a></li><li><a href="ch12-04-testing-the-librarys-functionality.html"><strong aria-hidden="true">12.4.</strong> Developing the Library’s Functionality with Test Driven Development</a></li><li><a href="ch12-05-working-with-environment-variables.html"><strong aria-hidden="true">12.5.</strong> Working with Environment Variables</a></li><li><a href="ch12-06-writing-to-stderr-instead-of-stdout.html"><strong aria-hidden="true">12.6.</strong> Writing Error Messages to Standard Error Instead of Standard Output</a></li></ol></li><li><a href="ch13-00-functional-features.html"><strong aria-hidden="true">13.</strong> Functional Language Features: Iterators and Closures</a></li><li><ol class="section"><li><a href="ch13-01-closures.html"><strong aria-hidden="true">13.1.</strong> Closures: Anonymous Functions that Can Capture Their Environment</a></li><li><a href="ch13-02-iterators.html"><strong aria-hidden="true">13.2.</strong> Processing a Series of Items with Iterators</a></li><li><a href="ch13-03-improving-our-io-project.html"><strong aria-hidden="true">13.3.</strong> Improving Our I/O Project</a></li><li><a href="ch13-04-performance.html"><strong aria-hidden="true">13.4.</strong> Comparing Performance: Loops vs. Iterators</a></li></ol></li><li><a href="ch14-00-more-about-cargo.html"><strong aria-hidden="true">14.</strong> More about Cargo and Crates.io</a></li><li><ol class="section"><li><a href="ch14-01-release-profiles.html"><strong aria-hidden="true">14.1.</strong> Customizing Builds with Release Profiles</a></li><li><a href="ch14-02-publishing-to-crates-io.html"><strong aria-hidden="true">14.2.</strong> Publishing a Crate to Crates.io</a></li><li><a href="ch14-03-cargo-workspaces.html"><strong aria-hidden="true">14.3.</strong> Cargo Workspaces</a></li><li><a href="ch14-04-installing-binaries.html"><strong aria-hidden="true">14.4.</strong> Installing Binaries from Crates.io with cargo install</a></li><li><a href="ch14-05-extending-cargo.html"><strong aria-hidden="true">14.5.</strong> Extending Cargo with Custom Commands</a></li></ol></li><li><a href="ch15-00-smart-pointers.html"><strong aria-hidden="true">15.</strong> Smart Pointers</a></li><li><ol class="section"><li><a href="ch15-01-box.html"><strong aria-hidden="true">15.1.</strong> Box<T> Points to Data on the Heap and Has a Known Size</a></li><li><a href="ch15-02-deref.html"><strong aria-hidden="true">15.2.</strong> The Deref Trait Allows Access to the Data Through a Reference</a></li><li><a href="ch15-03-drop.html"><strong aria-hidden="true">15.3.</strong> The Drop Trait Runs Code on Cleanup</a></li><li><a href="ch15-04-rc.html"><strong aria-hidden="true">15.4.</strong> Rc<T>, the Reference Counted Smart Pointer</a></li><li><a href="ch15-05-interior-mutability.html"><strong aria-hidden="true">15.5.</strong> RefCell<T> and the Interior Mutability Pattern</a></li><li><a href="ch15-06-reference-cycles.html"><strong aria-hidden="true">15.6.</strong> Creating Reference Cycles and Leaking Memory is Safe</a></li></ol></li><li><a href="ch16-00-concurrency.html"><strong aria-hidden="true">16.</strong> Fearless Concurrency</a></li><li><ol class="section"><li><a href="ch16-01-threads.html"><strong aria-hidden="true">16.1.</strong> Threads</a></li><li><a href="ch16-02-message-passing.html"><strong aria-hidden="true">16.2.</strong> Message Passing</a></li><li><a href="ch16-03-shared-state.html"><strong aria-hidden="true">16.3.</strong> Shared State</a></li><li><a href="ch16-04-extensible-concurrency-sync-and-send.html"><strong aria-hidden="true">16.4.</strong> Extensible Concurrency: Sync and Send</a></li></ol></li><li><a href="ch17-00-oop.html"><strong aria-hidden="true">17.</strong> Object Oriented Programming Features of Rust</a></li><li><ol class="section"><li><a href="ch17-01-what-is-oo.html"><strong aria-hidden="true">17.1.</strong> Characteristics of Object-Oriented Languages</a></li><li><a href="ch17-02-trait-objects.html"><strong aria-hidden="true">17.2.</strong> Using Trait Objects that Allow for Values of Different Types</a></li><li><a href="ch17-03-oo-design-patterns.html"><strong aria-hidden="true">17.3.</strong> Implementing an Object-Oriented Design Pattern</a></li></ol></li><li><a href="ch18-00-patterns.html"><strong aria-hidden="true">18.</strong> Patterns Match the Structure of Values</a></li><li><ol class="section"><li><a href="ch18-01-all-the-places-for-patterns.html"><strong aria-hidden="true">18.1.</strong> All the Places Patterns May be Used</a></li><li><a href="ch18-02-refutability.html"><strong aria-hidden="true">18.2.</strong> Refutability: Whether a Pattern Might Fail to Match</a></li><li><a href="ch18-03-pattern-syntax.html"><strong aria-hidden="true">18.3.</strong> All the Pattern Syntax</a></li></ol></li><li><a href="ch19-00-advanced-features.html"><strong aria-hidden="true">19.</strong> Advanced Features</a></li><li><ol class="section"><li><a href="ch19-01-unsafe-rust.html"><strong aria-hidden="true">19.1.</strong> Unsafe Rust</a></li><li><a href="ch19-02-advanced-lifetimes.html"><strong aria-hidden="true">19.2.</strong> Advanced Lifetimes</a></li><li><a href="ch19-03-advanced-traits.html"><strong aria-hidden="true">19.3.</strong> Advanced Traits</a></li><li><a href="ch19-04-advanced-types.html"><strong aria-hidden="true">19.4.</strong> Advanced Types</a></li><li><a href="ch19-05-advanced-functions-and-closures.html"><strong aria-hidden="true">19.5.</strong> Advanced Functions & Closures</a></li></ol></li><li><a href="ch20-00-final-project-a-web-server.html"><strong aria-hidden="true">20.</strong> Final Project: Building a Multithreaded Web Server</a></li><li><ol class="section"><li><a href="ch20-01-single-threaded.html"><strong aria-hidden="true">20.1.</strong> A Single Threaded Web Server</a></li><li><a href="ch20-02-multithreaded.html"><strong aria-hidden="true">20.2.</strong> Turning our Single Threaded Server into a Multithreaded Server</a></li><li><a href="ch20-03-graceful-shutdown-and-cleanup.html"><strong aria-hidden="true">20.3.</strong> Graceful Shutdown and Cleanup</a></li></ol></li><li><a href="appendix-00.html"><strong aria-hidden="true">21.</strong> Appendix</a></li><li><ol class="section"><li><a href="appendix-01-keywords.html"><strong aria-hidden="true">21.1.</strong> A - Keywords</a></li><li><a href="appendix-02-operators.html"><strong aria-hidden="true">21.2.</strong> B - Operators and Symbols</a></li><li><a href="appendix-03-derivable-traits.html"><strong aria-hidden="true">21.3.</strong> C - Derivable Traits</a></li><li><a href="appendix-04-macros.html" class="active"><strong aria-hidden="true">21.4.</strong> D - Macros</a></li><li><a href="appendix-05-translation.html"><strong aria-hidden="true">21.5.</strong> E - Translations</a></li><li><a href="appendix-06-newest-features.html"><strong aria-hidden="true">21.6.</strong> F - Newest Features</a></li><li><a href="appendix-07-nightly-rust.html"><strong aria-hidden="true">21.7.</strong> G - How Rust is Made and “Nightly Rust”</a></li></ol></li></ol> </nav> <div id="page-wrapper" class="page-wrapper"> <div class="page"> <div id="menu-bar" class="menu-bar"> <div id="menu-bar-sticky-container"> <div class="left-buttons"> <button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar"> <i class="fa fa-bars"></i> </button> <button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list"> <i class="fa fa-paint-brush"></i> </button> <ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu"> <li role="none"><button role="menuitem" class="theme" id="light">Light <span class="default">(default)</span></button></li> <li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li> <li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li> <li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li> <li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li> </ul> <button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar"> <i class="fa fa-search"></i> </button> </div> <h1 class="menu-title">The Rust Programming Language</h1> <div class="right-buttons"> <a href="print.html" title="Print this book" aria-label="Print this book"> <i id="print-button" class="fa fa-print"></i> </a> </div> </div> </div> <div id="search-wrapper" class="hidden"> <form id="searchbar-outer" class="searchbar-outer"> <input type="search" name="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header"> </form> <div id="searchresults-outer" class="searchresults-outer hidden"> <div id="searchresults-header" class="searchresults-header"></div> <ul id="searchresults"> </ul> </div> </div> <!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM --> <script type="text/javascript"> document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible'); document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible'); Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) { link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1); }); </script> <div id="content" class="content"> <main> <a class="header" href="appendix-04-macros.html#appendix-d-macros" id="appendix-d-macros"><h2>Appendix D: Macros</h2></a> <p>We’ve used macros like <code>println!</code> throughout this book but haven’t fully explored what a macro is and how it works. This appendix explains macros as follows:</p> <ul> <li>What macros are and how they differ from functions</li> <li>How to define a declarative macro to do metaprogramming</li> <li>How to define a procedural macro to create custom <code>derive</code> traits</li> </ul> <p>We’re covering the details of macros in an appendix because they’re still evolving in Rust. Macros have changed and, in the near future, will change at a quicker rate than the rest of the language and standard library since Rust 1.0, so this section is more likely to date than the rest of the book. Due to Rust’s stability guarantees, the code shown here will continue to work with future versions. But there may be additional capabilities or easier ways to write macros that weren’t available at the time of this publication. Bear that in mind when you try to implement anything from this appendix.</p> <a class="header" href="appendix-04-macros.html#the-difference-between-macros-and-functions" id="the-difference-between-macros-and-functions"><h3>The Difference Between Macros and Functions</h3></a> <p>Fundamentally, macros are a way of writing code that writes other code, which is known as <em>metaprogramming</em>. In Appendix C, we discussed the <code>derive</code> attribute, which generates an implementation of various traits for you. We’ve also used the <code>println!</code> and <code>vec!</code> macros throughout the book. All of these macros <em>expand</em> to produce more code than the code you’ve written manually.</p> <p>Metaprogramming is useful for reducing the amount of code you have to write and maintain, which is also one of the roles of functions. However, macros have some additional powers that functions don’t have.</p> <p>A function signature must declare the number and type of parameters the function has. Macros, on the other hand, can take a variable number of parameters: we can call <code>println!("hello")</code> with one argument or <code>println!("hello {}", name)</code> with two arguments. Also, macros are expanded before the compiler interprets the meaning of the code, so a macro can, for example, implement a trait on a given type. A function can’t, because it gets called at runtime and a trait needs to be implemented at compile time.</p> <p>The downside to implementing a macro instead of a function is that macro definitions are more complex than function definitions because you’re writing Rust code that writes Rust code. Due to this indirection, macro definitions are generally more difficult to read, understand, and maintain than function definitions.</p> <p>Another difference between macros and functions is that macro definitions aren’t namespaced within modules like function definitions are. To prevent unexpected name clashes when using external crates, you have to explicitly bring the macros into the scope of your project at the same time as you bring the external crate into scope, using the <code>#[macro_use]</code> annotation. The following example would bring all the macros defined in the <code>serde</code> crate into the scope of the current crate:</p> <pre><code class="language-rust ignore">#[macro_use] extern crate serde; </code></pre> <p>If <code>extern crate</code> was able to bring macros into scope by default without this explicit annotation, you would be prevented from using two crates that happened to define macros with the same name. In practice, this conflict doesn’t occur often, but the more crates you use, the more likely it is.</p> <p>There is one last important difference between macros and functions: you must define or bring macros into scope <em>before</em> you call them in a file, whereas you can define functions anywhere and call them anywhere.</p> <a class="header" href="appendix-04-macros.html#declarative-macros-with-macro_rules-for-general-metaprogramming" id="declarative-macros-with-macro_rules-for-general-metaprogramming"><h3>Declarative Macros with <code>macro_rules!</code> for General Metaprogramming</h3></a> <p>The most widely used form of macros in Rust are <em>declarative macros</em>. These are also sometimes referred to as <em>macros by example</em>, <em><code>macro_rules!</code> macros</em>, or just plain <em>macros</em>. At their core, declarative macros allow you to write something similar to a Rust <code>match</code> expression. As discussed in Chapter 6, <code>match</code> expressions are control structures that take an expression, compare the resulting value of the expression to patterns, and then run the code associated with the matching pattern. Macros also compare a value to patterns that have code associated with them; in this situation, the value is the literal Rust source code passed to the macro, the patterns are compared with the structure of that source code, and the code associated with each pattern is the code that replaces the code passed to the macro. This all happens during compilation.</p> <p>To define a macro, you use the <code>macro_rules!</code> construct. Let’s explore how to use <code>macro_rules!</code> by looking at how the <code>vec!</code> macro is defined. Chapter 8 covered how we can use the <code>vec!</code> macro to create a new vector with particular values. For example, the following macro creates a new vector with three integers inside:</p> <pre><pre class="playpen"><code class="language-rust"> # #![allow(unused_variables)] #fn main() { let v: Vec<u32> = vec![1, 2, 3]; #}</code></pre></pre> <p>We could also use the <code>vec!</code> macro to make a vector of two integers or a vector of five string slices: we wouldn’t be able to use a function to do the same because we wouldn’t know the number or type of values up front.</p> <p>Let’s look at a slightly simplified definition of the <code>vec!</code> macro in Listing D-1:</p> <pre><pre class="playpen"><code class="language-rust"> # #![allow(unused_variables)] #fn main() { #[macro_export] macro_rules! vec { ( $( $x:expr ),* ) => { { let mut temp_vec = Vec::new(); $( temp_vec.push($x); )* temp_vec } }; } #}</code></pre></pre> <p><span class="caption">Listing D-1: A simplified version of the <code>vec!</code> macro definition</span></p> <blockquote> <p>Note: The actual definition of the <code>vec!</code> macro in the standard library includes code to preallocate the correct amount of memory up front. That code is an optimization that we don’t include here to make the example simpler.</p> </blockquote> <p>The <code>#[macro_export]</code> annotation indicates that this macro should be made available whenever the crate in which we’re defining the macro is imported. Without this annotation, even if someone depending on this crate uses the <code>#[macro_use]</code> annotation, the macro wouldn’t be brought into scope.</p> <p>We then start the macro definition with <code>macro_rules!</code> and the name of the macro we’re defining <em>without</em> the exclamation mark. The name, in this case <code>vec</code>, is followed by curly brackets denoting the body of the macro definition.</p> <p>The structure in the <code>vec!</code> body is similar to the structure of a <code>match</code> expression. Here we have one arm with the pattern <code>( $( $x:expr ),* )</code>, followed by <code>=></code> and the block of code associated with this pattern. If the pattern matches, the associated block of code will be emitted. Given that this is the only pattern in this macro, there is only one valid way to match; any other will be an error. More complex macros will have more than one arm.</p> <p>Valid pattern syntax in macro definitions is different than the pattern syntax covered in Chapter 18 because macro patterns are matched against Rust code structure rather than values. Let’s walk through what the pieces of the pattern in Listing D-1 mean; for the full macro pattern syntax, see <a href="../../reference/macros.html">the reference</a>.</p> <p>First, a set of parentheses encompasses the whole pattern. Next comes a dollar sign (<code>$</code>) followed by a set of parentheses, which captures values that match the pattern within the parentheses for use in the replacement code. Within <code>$()</code> is <code>$x:expr</code>, which matches any Rust expression and gives the expression the name <code>$x</code>.</p> <p>The comma following <code>$()</code> indicates that a literal comma separator character could optionally appear after the code that matches the code captured in <code>$()</code>. The <code>*</code> following the comma specifies that the pattern matches zero or more of whatever precedes the <code>*</code>.</p> <p>When we call this macro with <code>vec![1, 2, 3];</code>, the <code>$x</code> pattern matches three times with the three expressions <code>1</code>, <code>2</code>, and <code>3</code>.</p> <p>Now let’s look at the pattern in the body of the code associated with this arm: the <code>temp_vec.push()</code> code within the <code>$()*</code> part is generated for each part that matches <code>$()</code> in the pattern, zero or more times depending on how many times the pattern matches. The <code>$x</code> is replaced with each expression matched. When we call this macro with <code>vec![1, 2, 3];</code>, the code generated that replaces this macro call will be the following:</p> <pre><code class="language-rust ignore">let mut temp_vec = Vec::new(); temp_vec.push(1); temp_vec.push(2); temp_vec.push(3); temp_vec </code></pre> <p>We’ve defined a macro that can take any number of arguments of any type and can generate code to create a vector containing the specified elements.</p> <p>Given that most Rust programmers will <em>use</em> macros more than <em>write</em> macros, we won’t discuss <code>macro_rules!</code> any further. To learn more about how to write macros, consult the online documentation or other resources, such as <a href="https://danielkeep.github.io/tlborm/book/index.html">“The Little Book of Rust Macros”</a>.</p> <a class="header" href="appendix-04-macros.html#procedural-macros-for-custom-derive" id="procedural-macros-for-custom-derive"><h3>Procedural Macros for Custom <code>derive</code></h3></a> <p>The second form of macros is called <em>procedural macros</em> because they’re more like functions (which are a type of procedure). Procedural macros accept some Rust code as an input, operate on that code, and produce some Rust code as an output rather than matching against patterns and replacing the code with other code as declarative macros do. At the time of this writing, you can only define procedural macros to allow your traits to be implemented on a type by specifying the trait name in a <code>derive</code> annotation.</p> <p>We’ll create a crate named <code>hello_macro</code> that defines a trait named <code>HelloMacro</code> with one associated function named <code>hello_macro</code>. Rather than making our crate users implement the <code>HelloMacro</code> trait for each of their types, we’ll provide a procedural macro so users can annotate their type with <code>#[derive(HelloMacro)]</code> to get a default implementation of the <code>hello_macro</code> function. The default implementation will print <code>Hello, Macro! My name is TypeName!</code> where <code>TypeName</code> is the name of the type on which this trait has been defined. In other words, we’ll write a crate that enables another programmer to write code like Listing D-2 using our crate.</p> <p><span class="filename">Filename: src/main.rs</span></p> <pre><code class="language-rust ignore">extern crate hello_macro; #[macro_use] extern crate hello_macro_derive; use hello_macro::HelloMacro; #[derive(HelloMacro)] struct Pancakes; fn main() { Pancakes::hello_macro(); } </code></pre> <p><span class="caption">Listing D-2: The code a user of our crate will be able to write when using our procedural macro</span></p> <p>This code will print <code>Hello, Macro! My name is Pancakes!</code> when we’re done. The first step is to make a new library crate, like this:</p> <pre><code class="language-text">$ cargo new hello_macro --lib </code></pre> <p>Next, we’ll define the <code>HelloMacro</code> trait and its associated function:</p> <p><span class="filename">Filename: src/lib.rs</span></p> <pre><pre class="playpen"><code class="language-rust"> # #![allow(unused_variables)] #fn main() { pub trait HelloMacro { fn hello_macro(); } #}</code></pre></pre> <p>We have a trait and its function. At this point, our crate user could implement the trait to achieve the desired functionality, like so:</p> <pre><code class="language-rust ignore">extern crate hello_macro; use hello_macro::HelloMacro; struct Pancakes; impl HelloMacro for Pancakes { fn hello_macro() { println!("Hello, Macro! My name is Pancakes!"); } } fn main() { Pancakes::hello_macro(); } </code></pre> <p>However, they would need to write the implementation block for each type they wanted to use with <code>hello_macro</code>; we want to spare them from having to do this work.</p> <p>Additionally, we can’t yet provide a default implementation for the <code>hello_macro</code> function that will print the name of the type the trait is implemented on: Rust doesn’t have reflection capabilities, so it can’t look up the type’s name at runtime. We need a macro to generate code at compile time.</p> <p>The next step is to define the procedural macro. At the time of this writing, procedural macros need to be in their own crate. Eventually, this restriction might be lifted. The convention for structuring crates and macro crates is as follows: for a crate named <code>foo</code>, a custom derive procedural macro crate is called <code>foo_derive</code>. Let’s start a new crate called <code>hello_macro_derive</code> inside our <code>hello_macro</code> project:</p> <pre><code class="language-text">$ cargo new hello_macro_derive --lib </code></pre> <p>Our two crates are tightly related, so we create the procedural macro crate within the directory of our <code>hello_macro</code> crate. If we change the trait definition in <code>hello_macro</code>, we’ll have to change the implementation of the procedural macro in <code>hello_macro_derive</code> as well. The two crates will need to be published separately, and programmers using these crates will need to add both as dependencies and bring them both into scope. We could instead have the <code>hello_macro</code> crate use <code>hello_macro_derive</code> as a dependency and reexport the procedural macro code. But the way we’ve structured the project makes it possible for programmers to use <code>hello_macro</code> even if they don’t want the <code>derive</code> functionality.</p> <p>We need to declare the <code>hello_macro_derive</code> crate as a procedural macro crate. We’ll also need functionality from the <code>syn</code> and <code>quote</code> crates, as you’ll see in a moment, so we need to add them as dependencies. Add the following to the <em>Cargo.toml</em> file for <code>hello_macro_derive</code>:</p> <p><span class="filename">Filename: hello_macro_derive/Cargo.toml</span></p> <pre><code class="language-toml">[lib] proc-macro = true [dependencies] syn = "0.11.11" quote = "0.3.15" </code></pre> <p>To start defining the procedural macro, place the code in Listing D-3 into your <em>src/lib.rs</em> file for the <code>hello_macro_derive</code> crate. Note that this code won’t compile until we add a definition for the <code>impl_hello_macro</code> function.</p> <p>Notice the way we’ve split the functions in D-3; this will be the same for almost every procedural macro crate you see or create, because it makes writing a procedural macro more convenient. What you choose to do in the place where the <code>impl_hello_macro</code> function is called will be different depending on your procedural macro’s purpose.</p> <p><span class="filename">Filename: hello_macro_derive/src/lib.rs</span></p> <pre><code class="language-rust ignore">extern crate proc_macro; extern crate syn; #[macro_use] extern crate quote; use proc_macro::TokenStream; #[proc_macro_derive(HelloMacro)] pub fn hello_macro_derive(input: TokenStream) -> TokenStream { // Construct a string representation of the type definition let s = input.to_string(); // Parse the string representation let ast = syn::parse_derive_input(&s).unwrap(); // Build the impl let gen = impl_hello_macro(&ast); // Return the generated impl gen.parse().unwrap() } </code></pre> <p><span class="caption">Listing D-3: Code that most procedural macro crates will need to have for processing Rust code</span></p> <p>We’ve introduced three new crates: <code>proc_macro</code>, <a href="https://crates.io/crates/syn"><code>syn</code></a>, and <a href="https://crates.io/crates/quote"><code>quote</code></a>. The <code>proc_macro</code> crate comes with Rust, so we didn’t need to add that to the dependencies in <em>Cargo.toml</em>. The <code>proc_macro</code> crate allows us to convert Rust code into a string containing that Rust code. The <code>syn</code> crate parses Rust code from a string into a data structure that we can perform operations on. The <code>quote</code> crate takes <code>syn</code> data structures and turns them back into Rust code. These crates make it much simpler to parse any sort of Rust code we might want to handle: writing a full parser for Rust code is no simple task.</p> <p>The <code>hello_macro_derive</code> function will get called when a user of our library specifies <code>#[derive(HelloMacro)]</code> on a type. The reason is that we’ve annotated the <code>hello_macro_derive</code> function here with <code>proc_macro_derive</code> and specified the name, <code>HelloMacro</code>, which matches our trait name; that’s the convention most procedural macros follow.</p> <p>This function first converts the <code>input</code> from a <code>TokenStream</code> to a <code>String</code> by calling <code>to_string</code>. This <code>String</code> is a string representation of the Rust code for which we are deriving <code>HelloMacro</code>. In the example in Listing D-2, <code>s</code> will have the <code>String</code> value <code>struct Pancakes;</code> because that is the Rust code we added the <code>#[derive(HelloMacro)]</code> annotation to.</p> <blockquote> <p>Note: At the time of this writing, you can only convert a <code>TokenStream</code> to a string. A richer API will exist in the future.</p> </blockquote> <p>Now we need to parse the Rust code <code>String</code> into a data structure that we can then interpret and perform operations on. This is where <code>syn</code> comes into play. The <code>parse_derive_input</code> function in <code>syn</code> takes a <code>String</code> and returns a <code>DeriveInput</code> struct representing the parsed Rust code. The following code shows the relevant parts of the <code>DeriveInput</code> struct we get from parsing the string <code>struct Pancakes;</code>:</p> <pre><code class="language-rust ignore">DeriveInput { // --snip-- ident: Ident( "Pancakes" ), body: Struct( Unit ) } </code></pre> <p>The fields of this struct show that the Rust code we’ve parsed is a unit struct with the <code>ident</code> (identifier, meaning the name) of <code>Pancakes</code>. There are more fields on this struct for describing all sorts of Rust code; check the <a href="https://docs.rs/syn/0.11.11/syn/struct.DeriveInput.html"><code>syn</code> documentation for <code>DeriveInput</code></a> for more information.</p> <p>At this point, we haven’t defined the <code>impl_hello_macro</code> function, which is where we’ll build the new Rust code we want to include. But before we do, note that the last part of this <code>hello_macro_derive</code> function uses the <code>parse</code> function from the <code>quote</code> crate to turn the output of the <code>impl_hello_macro</code> function back into a <code>TokenStream</code>. The returned <code>TokenStream</code> is added to the code that our crate users write, so when they compile their crate, they get extra functionality that we provide.</p> <p>You might have noticed that we’re calling <code>unwrap</code> to panic if the calls to the <code>parse_derive_input</code> or <code>parse</code> functions fail here. Panicking on errors is necessary in procedural macro code because <code>proc_macro_derive</code> functions must return <code>TokenStream</code> rather than <code>Result</code> to conform to the procedural macro API. We’ve chosen to simplify this example by using <code>unwrap</code>; in production code, you should provide more specific error messages about what went wrong by using <code>panic!</code> or <code>expect</code>.</p> <p>Now that we have the code to turn the annotated Rust code from a <code>TokenStream</code> into a <code>String</code> and a <code>DeriveInput</code> instance, let’s generate the code that implements the <code>HelloMacro</code> trait on the annotated type:</p> <p><span class="filename">Filename: hello_macro_derive/src/lib.rs</span></p> <pre><code class="language-rust ignore">fn impl_hello_macro(ast: &syn::DeriveInput) -> quote::Tokens { let name = &ast.ident; quote! { impl HelloMacro for #name { fn hello_macro() { println!("Hello, Macro! My name is {}", stringify!(#name)); } } } } </code></pre> <p>We get an <code>Ident</code> struct instance containing the name (identifier) of the annotated type using <code>ast.ident</code>. The code in Listing D-2 specifies that the <code>name</code> will be <code>Ident("Pancakes")</code>.</p> <p>The <code>quote!</code> macro lets us write the Rust code that we want to return and convert it into <code>quote::Tokens</code>. This macro also provides some very cool templating mechanics; we can write <code>#name</code> and <code>quote!</code> will replace it with the value in the variable named <code>name</code>. You can even do some repetition similar to the way regular macros work. Check out <a href="https://docs.rs/quote">the <code>quote</code> crate’s docs</a> for a thorough introduction.</p> <p>We want our procedural macro to generate an implementation of our <code>HelloMacro</code> trait for the type the user annotated, which we can get by using <code>#name</code>. The trait implementation has one function, <code>hello_macro</code>, whose body contains the functionality we want to provide: printing <code>Hello, Macro! My name is</code> and then the name of the annotated type.</p> <p>The <code>stringify!</code> macro used here is built into Rust. It takes a Rust expression, such as <code>1 + 2</code>, and at compile time turns the expression into a string literal, such as <code>"1 + 2"</code>. This is different than <code>format!</code> or <code>println!</code>, which evaluate the expression and then turn the result into a <code>String</code>. There is a possibility that the <code>#name</code> input might be an expression to print literally, so we use <code>stringify!</code>. Using <code>stringify!</code> also saves an allocation by converting <code>#name</code> to a string literal at compile time.</p> <p>At this point, <code>cargo build</code> should complete successfully in both <code>hello_macro</code> and <code>hello_macro_derive</code>. Let’s hook up these crates to the code in Listing D-2 to see the procedural macro in action! Create a new binary project in your <em>projects</em> directory using <code>cargo new --bin pancakes</code>. We need to add <code>hello_macro</code> and <code>hello_macro_derive</code> as dependencies in the <code>pancakes</code> crate’s <em>Cargo.toml</em>. If you’re publishing your versions of <code>hello_macro</code> and <code>hello_macro_derive</code> to <em>https://crates.io/</em>, they would be regular dependencies; if not, you can specify them as <code>path</code> dependencies as follows:</p> <pre><code class="language-toml">[dependencies] hello_macro = { path = "../hello_macro" } hello_macro_derive = { path = "../hello_macro/hello_macro_derive" } </code></pre> <p>Put the code from Listing D-2 into <em>src/main.rs</em>, and run <code>cargo run</code>: it should print <code>Hello, Macro! My name is Pancakes!</code> The implementation of the <code>HelloMacro</code> trait from the procedural macro was included without the <code>pancakes</code> crate needing to implement it; the <code>#[derive(HelloMacro)]</code> added the trait implementation.</p> <a class="header" href="appendix-04-macros.html#the-future-of-macros" id="the-future-of-macros"><h3>The Future of Macros</h3></a> <p>In the future, Rust will expand declarative and procedural macros. Rust will use a better declarative macro system with the <code>macro</code> keyword and will add more types of procedural macros for more powerful tasks than just <code>derive</code>. These systems are still under development at the time of this publication; please consult the online Rust documentation for the latest information.</p> </main> <nav class="nav-wrapper" aria-label="Page navigation"> <!-- Mobile navigation buttons --> <a rel="prev" href="appendix-03-derivable-traits.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left"> <i class="fa fa-angle-left"></i> </a> <a rel="next" href="appendix-05-translation.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right"> <i class="fa fa-angle-right"></i> </a> <div style="clear: both"></div> </nav> </div> </div> <nav class="nav-wide-wrapper" aria-label="Page navigation"> <a href="appendix-03-derivable-traits.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left"> <i class="fa fa-angle-left"></i> </a> <a href="appendix-05-translation.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right"> <i class="fa fa-angle-right"></i> </a> </nav> </div> <script src="searchindex.js" type="text/javascript" charset="utf-8"></script> <script src="elasticlunr.min.js" type="text/javascript" charset="utf-8"></script> <script src="mark.min.js" type="text/javascript" charset="utf-8"></script> <script src="searcher.js" type="text/javascript" charset="utf-8"></script> <script src="clipboard.min.js" type="text/javascript" charset="utf-8"></script> <script src="highlight.js" type="text/javascript" charset="utf-8"></script> <script src="book.js" type="text/javascript" charset="utf-8"></script> <!-- Custom JS scripts --> </body> </html>