blob: c61261bf522130ca993f83570491d2384feee861 [file] [edit]
<!DOCTYPE HTML>
<html lang="en" class="sidebar-visible no-js light">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>Macro expansion - Guide to Rustc Development</title>
<!-- Custom HTML head -->
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<meta name="description" content="A guide to developing rustc">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff" />
<link rel="icon" href="favicon.svg">
<link rel="shortcut icon" href="favicon.png">
<link rel="stylesheet" href="css/variables.css">
<link rel="stylesheet" href="css/general.css">
<link rel="stylesheet" href="css/chrome.css">
<link rel="stylesheet" href="css/print.css" media="print">
<!-- Fonts -->
<link rel="stylesheet" href="FontAwesome/css/font-awesome.css">
<link rel="stylesheet" href="fonts/fonts.css">
<!-- Highlight.js Stylesheets -->
<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>
<!-- Provide site root to javascript -->
<script type="text/javascript">
var path_to_root = "";
var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "navy" : "light";
</script>
<!-- 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 = default_theme; }
var html = document.querySelector('html');
html.classList.remove('no-js')
html.classList.remove('light')
html.classList.add(theme);
html.classList.add('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">
<div class="sidebar-scrollbox">
<ol class="chapter"><li class="chapter-item affix "><a href="about-this-guide.html">About this guide</a></li><li class="chapter-item affix "><a href="getting-started.html">Getting Started</a></li><li class="spacer"></li><li class="chapter-item affix "><li class="part-title">Building and debugging rustc</li><li class="chapter-item "><a href="building/how-to-build-and-run.html"><strong aria-hidden="true">1.</strong> How to Build and Run the Compiler</a><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item "><a href="building/prerequisites.html"><strong aria-hidden="true">1.1.</strong> Prerequisites</a></li><li class="chapter-item "><a href="building/suggested.html"><strong aria-hidden="true">1.2.</strong> Suggested Workflows</a></li><li class="chapter-item "><a href="building/build-install-distribution-artifacts.html"><strong aria-hidden="true">1.3.</strong> Distribution artifacts</a></li><li class="chapter-item "><a href="building/compiler-documenting.html"><strong aria-hidden="true">1.4.</strong> Documenting Compiler</a></li><li class="chapter-item "><a href="rustdoc.html"><strong aria-hidden="true">1.5.</strong> Rustdoc overview</a></li><li class="chapter-item "><a href="building/new-target.html"><strong aria-hidden="true">1.6.</strong> Adding a new target</a></li></ol></li><li class="chapter-item "><a href="tests/intro.html"><strong aria-hidden="true">2.</strong> The compiler testing framework</a><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item "><a href="tests/running.html"><strong aria-hidden="true">2.1.</strong> Running tests</a></li><li class="chapter-item "><a href="tests/adding.html"><strong aria-hidden="true">2.2.</strong> Adding new tests</a></li><li class="chapter-item "><a href="compiletest.html"><strong aria-hidden="true">2.3.</strong> Using compiletest commands to control test execution</a></li></ol></li><li class="chapter-item "><a href="compiler-debugging.html"><strong aria-hidden="true">3.</strong> Debugging the Compiler</a><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item "><a href="tracing.html"><strong aria-hidden="true">3.1.</strong> Using the tracing/logging instrumentation</a></li></ol></li><li class="chapter-item "><a href="profiling.html"><strong aria-hidden="true">4.</strong> Profiling the compiler</a><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item "><a href="profiling/with_perf.html"><strong aria-hidden="true">4.1.</strong> with the linux perf tool</a></li><li class="chapter-item "><a href="profiling/wpa_profiling.html"><strong aria-hidden="true">4.2.</strong> with Windows Performance Analyzer</a></li></ol></li><li class="chapter-item "><a href="crates-io.html"><strong aria-hidden="true">5.</strong> crates.io Dependencies</a></li><li class="chapter-item affix "><li class="part-title">Contributing to Rust</li><li class="chapter-item "><a href="contributing.html"><strong aria-hidden="true">6.</strong> Introduction</a></li><li class="chapter-item "><a href="compiler-team.html"><strong aria-hidden="true">7.</strong> About the compiler team</a></li><li class="chapter-item "><a href="git.html"><strong aria-hidden="true">8.</strong> Using Git</a></li><li class="chapter-item "><a href="rustbot.html"><strong aria-hidden="true">9.</strong> Mastering @rustbot</a></li><li class="chapter-item "><a href="walkthrough.html"><strong aria-hidden="true">10.</strong> Walkthrough: a typical contribution</a></li><li class="chapter-item "><a href="bug-fix-procedure.html"><strong aria-hidden="true">11.</strong> Bug Fix Procedure</a></li><li class="chapter-item "><a href="implementing_new_features.html"><strong aria-hidden="true">12.</strong> Implementing new features</a></li><li class="chapter-item "><a href="stability.html"><strong aria-hidden="true">13.</strong> Stability attributes</a></li><li class="chapter-item "><a href="stabilization_guide.html"><strong aria-hidden="true">14.</strong> Stabilizing Features</a></li><li class="chapter-item "><a href="feature-gates.html"><strong aria-hidden="true">15.</strong> Feature Gates</a></li><li class="chapter-item "><a href="conventions.html"><strong aria-hidden="true">16.</strong> Coding conventions</a></li><li class="chapter-item "><a href="notification-groups/about.html"><strong aria-hidden="true">17.</strong> Notification groups</a><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item "><a href="notification-groups/arm.html"><strong aria-hidden="true">17.1.</strong> ARM</a></li><li class="chapter-item "><a href="notification-groups/cleanup-crew.html"><strong aria-hidden="true">17.2.</strong> Cleanup Crew</a></li><li class="chapter-item "><a href="notification-groups/llvm.html"><strong aria-hidden="true">17.3.</strong> LLVM</a></li><li class="chapter-item "><a href="notification-groups/risc-v.html"><strong aria-hidden="true">17.4.</strong> RISC-V</a></li><li class="chapter-item "><a href="notification-groups/windows.html"><strong aria-hidden="true">17.5.</strong> Windows</a></li></ol></li><li class="chapter-item "><a href="licenses.html"><strong aria-hidden="true">18.</strong> Licenses</a></li><li class="chapter-item affix "><li class="part-title">High-level Compiler Architecture</li><li class="chapter-item "><a href="part-2-intro.html"><strong aria-hidden="true">19.</strong> Prologue</a></li><li class="chapter-item "><a href="overview.html"><strong aria-hidden="true">20.</strong> Overview of the Compiler</a></li><li class="chapter-item "><a href="compiler-src.html"><strong aria-hidden="true">21.</strong> The compiler source code</a></li><li class="chapter-item "><a href="building/bootstrapping.html"><strong aria-hidden="true">22.</strong> Bootstrapping</a></li><li class="chapter-item "><a href="query.html"><strong aria-hidden="true">23.</strong> Queries: demand-driven compilation</a><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item "><a href="queries/query-evaluation-model-in-detail.html"><strong aria-hidden="true">23.1.</strong> The Query Evaluation Model in Detail</a></li><li class="chapter-item "><a href="queries/incremental-compilation.html"><strong aria-hidden="true">23.2.</strong> Incremental compilation</a></li><li class="chapter-item "><a href="queries/incremental-compilation-in-detail.html"><strong aria-hidden="true">23.3.</strong> Incremental compilation In Detail</a></li><li class="chapter-item "><a href="incrcomp-debugging.html"><strong aria-hidden="true">23.4.</strong> Debugging and Testing</a></li><li class="chapter-item "><a href="salsa.html"><strong aria-hidden="true">23.5.</strong> Salsa</a></li></ol></li><li class="chapter-item "><a href="memory.html"><strong aria-hidden="true">24.</strong> Memory Management in Rustc</a></li><li class="chapter-item "><a href="serialization.html"><strong aria-hidden="true">25.</strong> Serialization in Rustc</a></li><li class="chapter-item "><a href="parallel-rustc.html"><strong aria-hidden="true">26.</strong> Parallel Compilation</a></li><li class="chapter-item "><a href="rustdoc-internals.html"><strong aria-hidden="true">27.</strong> Rustdoc internals</a></li><li class="chapter-item affix "><li class="part-title">Source Code Representation</li><li class="chapter-item "><a href="part-3-intro.html"><strong aria-hidden="true">28.</strong> Prologue</a></li><li class="chapter-item "><a href="cli.html"><strong aria-hidden="true">29.</strong> Command-line arguments</a></li><li class="chapter-item "><a href="rustc-driver.html"><strong aria-hidden="true">30.</strong> The Rustc Driver and Interface</a><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item "><a href="rustc-driver-interacting-with-the-ast.html"><strong aria-hidden="true">30.1.</strong> Ex: Type checking through rustc_interface</a></li><li class="chapter-item "><a href="rustc-driver-getting-diagnostics.html"><strong aria-hidden="true">30.2.</strong> Ex: Getting diagnostics through rustc_interface</a></li></ol></li><li class="chapter-item expanded "><a href="syntax-intro.html"><strong aria-hidden="true">31.</strong> Syntax and the AST</a><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item "><a href="the-parser.html"><strong aria-hidden="true">31.1.</strong> Lexing and Parsing</a></li><li class="chapter-item expanded "><a href="macro-expansion.html" class="active"><strong aria-hidden="true">31.2.</strong> Macro expansion</a></li><li class="chapter-item "><a href="name-resolution.html"><strong aria-hidden="true">31.3.</strong> Name resolution</a></li><li class="chapter-item "><a href="test-implementation.html"><strong aria-hidden="true">31.4.</strong> #[test] Implementation</a></li><li class="chapter-item "><a href="panic-implementation.html"><strong aria-hidden="true">31.5.</strong> Panic Implementation</a></li><li class="chapter-item "><a href="ast-validation.html"><strong aria-hidden="true">31.6.</strong> AST Validation</a></li><li class="chapter-item "><a href="feature-gate-ck.html"><strong aria-hidden="true">31.7.</strong> Feature Gate Checking</a></li><li class="chapter-item "><a href="lang-items.html"><strong aria-hidden="true">31.8.</strong> Lang Items</a></li></ol></li><li class="chapter-item "><a href="hir.html"><strong aria-hidden="true">32.</strong> The HIR (High-level IR)</a><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item "><a href="lowering.html"><strong aria-hidden="true">32.1.</strong> Lowering AST to HIR</a></li><li class="chapter-item "><a href="hir-debugging.html"><strong aria-hidden="true">32.2.</strong> Debugging</a></li></ol></li><li class="chapter-item "><a href="thir.html"><strong aria-hidden="true">33.</strong> The THIR (Typed High-level IR)</a></li><li class="chapter-item "><a href="mir/index.html"><strong aria-hidden="true">34.</strong> The MIR (Mid-level IR)</a><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item "><a href="mir/construction.html"><strong aria-hidden="true">34.1.</strong> MIR construction</a></li><li class="chapter-item "><a href="mir/visitor.html"><strong aria-hidden="true">34.2.</strong> MIR visitor and traversal</a></li><li class="chapter-item "><a href="mir/passes.html"><strong aria-hidden="true">34.3.</strong> MIR passes: getting the MIR for a function</a></li></ol></li><li class="chapter-item "><a href="identifiers.html"><strong aria-hidden="true">35.</strong> Identifiers in the Compiler</a></li><li class="chapter-item "><a href="closure.html"><strong aria-hidden="true">36.</strong> Closure expansion</a></li><li class="chapter-item affix "><li class="part-title">Analysis</li><li class="chapter-item "><a href="part-4-intro.html"><strong aria-hidden="true">37.</strong> Prologue</a></li><li class="chapter-item "><a href="ty.html"><strong aria-hidden="true">38.</strong> The ty module: representing types</a><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item "><a href="generics.html"><strong aria-hidden="true">38.1.</strong> Generics and substitutions</a></li><li class="chapter-item "><a href="ty-fold.html"><strong aria-hidden="true">38.2.</strong> TypeFolder and TypeFoldable</a></li><li class="chapter-item "><a href="generic_arguments.html"><strong aria-hidden="true">38.3.</strong> Generic arguments</a></li><li class="chapter-item "><a href="constants.html"><strong aria-hidden="true">38.4.</strong> Constants in the type system</a></li></ol></li><li class="chapter-item "><a href="type-inference.html"><strong aria-hidden="true">39.</strong> Type inference</a></li><li class="chapter-item "><a href="traits/resolution.html"><strong aria-hidden="true">40.</strong> Trait solving</a><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item "><a href="early-late-bound.html"><strong aria-hidden="true">40.1.</strong> Early and Late Bound Parameters</a></li><li class="chapter-item "><a href="traits/hrtb.html"><strong aria-hidden="true">40.2.</strong> Higher-ranked trait bounds</a></li><li class="chapter-item "><a href="traits/caching.html"><strong aria-hidden="true">40.3.</strong> Caching subtleties</a></li><li class="chapter-item "><a href="traits/specialization.html"><strong aria-hidden="true">40.4.</strong> Specialization</a></li><li class="chapter-item "><a href="traits/chalk.html"><strong aria-hidden="true">40.5.</strong> Chalk-based trait solving</a><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item "><a href="traits/lowering-to-logic.html"><strong aria-hidden="true">40.5.1.</strong> Lowering to logic</a></li><li class="chapter-item "><a href="traits/goals-and-clauses.html"><strong aria-hidden="true">40.5.2.</strong> Goals and clauses</a></li><li class="chapter-item "><a href="traits/canonical-queries.html"><strong aria-hidden="true">40.5.3.</strong> Canonical queries</a></li></ol></li></ol></li><li class="chapter-item "><a href="type-checking.html"><strong aria-hidden="true">41.</strong> Type checking</a><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item "><a href="method-lookup.html"><strong aria-hidden="true">41.1.</strong> Method Lookup</a></li><li class="chapter-item "><a href="variance.html"><strong aria-hidden="true">41.2.</strong> Variance</a></li><li class="chapter-item "><a href="opaque-types-type-alias-impl-trait.html"><strong aria-hidden="true">41.3.</strong> Opaque Types</a></li></ol></li><li class="chapter-item "><a href="pat-exhaustive-checking.html"><strong aria-hidden="true">42.</strong> Pattern and Exhaustiveness Checking</a></li><li class="chapter-item "><a href="mir/dataflow.html"><strong aria-hidden="true">43.</strong> MIR dataflow</a></li><li class="chapter-item "><a href="borrow_check.html"><strong aria-hidden="true">44.</strong> The borrow checker</a><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item "><a href="borrow_check/moves_and_initialization.html"><strong aria-hidden="true">44.1.</strong> Tracking moves and initialization</a><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item "><a href="borrow_check/moves_and_initialization/move_paths.html"><strong aria-hidden="true">44.1.1.</strong> Move paths</a></li></ol></li><li class="chapter-item "><a href="borrow_check/type_check.html"><strong aria-hidden="true">44.2.</strong> MIR type checker</a></li><li class="chapter-item "><a href="borrow_check/region_inference.html"><strong aria-hidden="true">44.3.</strong> Region inference</a><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item "><a href="borrow_check/region_inference/constraint_propagation.html"><strong aria-hidden="true">44.3.1.</strong> Constraint propagation</a></li><li class="chapter-item "><a href="borrow_check/region_inference/lifetime_parameters.html"><strong aria-hidden="true">44.3.2.</strong> Lifetime parameters</a></li><li class="chapter-item "><a href="borrow_check/region_inference/member_constraints.html"><strong aria-hidden="true">44.3.3.</strong> Member constraints</a></li><li class="chapter-item "><a href="borrow_check/region_inference/placeholders_and_universes.html"><strong aria-hidden="true">44.3.4.</strong> Placeholders and universes</a></li><li class="chapter-item "><a href="borrow_check/region_inference/closure_constraints.html"><strong aria-hidden="true">44.3.5.</strong> Closure constraints</a></li><li class="chapter-item "><a href="borrow_check/region_inference/error_reporting.html"><strong aria-hidden="true">44.3.6.</strong> Error reporting</a></li></ol></li><li class="chapter-item "><a href="borrow_check/two_phase_borrows.html"><strong aria-hidden="true">44.4.</strong> Two-phase-borrows</a></li></ol></li><li class="chapter-item "><a href="param_env.html"><strong aria-hidden="true">45.</strong> Parameter Environments</a></li><li class="chapter-item "><a href="diagnostics.html"><strong aria-hidden="true">46.</strong> Errors and Lints</a><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item "><a href="diagnostics/sessiondiagnostic.html"><strong aria-hidden="true">46.1.</strong> Creating Errors With SessionDiagnostic</a></li><li class="chapter-item "><a href="diagnostics/lintstore.html"><strong aria-hidden="true">46.2.</strong> LintStore</a></li><li class="chapter-item "><a href="diagnostics/diagnostic-codes.html"><strong aria-hidden="true">46.3.</strong> Diagnostic Codes</a></li><li class="chapter-item "><a href="diagnostics/diagnostic-items.html"><strong aria-hidden="true">46.4.</strong> Diagnostic Items</a></li></ol></li><li class="chapter-item "><li class="part-title">MIR to Binaries</li><li class="chapter-item "><a href="part-5-intro.html"><strong aria-hidden="true">47.</strong> Prologue</a></li><li class="chapter-item "><a href="mir/optimizations.html"><strong aria-hidden="true">48.</strong> MIR optimizations</a></li><li class="chapter-item "><a href="mir/debugging.html"><strong aria-hidden="true">49.</strong> Debugging</a></li><li class="chapter-item "><a href="const-eval.html"><strong aria-hidden="true">50.</strong> Constant evaluation</a><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item "><a href="miri.html"><strong aria-hidden="true">50.1.</strong> miri const evaluator</a></li></ol></li><li class="chapter-item "><a href="backend/monomorph.html"><strong aria-hidden="true">51.</strong> Monomorphization</a></li><li class="chapter-item "><a href="backend/lowering-mir.html"><strong aria-hidden="true">52.</strong> Lowering MIR</a></li><li class="chapter-item "><a href="backend/codegen.html"><strong aria-hidden="true">53.</strong> Code Generation</a><a class="toggle"><div></div></a></li><li><ol class="section"><li class="chapter-item "><a href="backend/updating-llvm.html"><strong aria-hidden="true">53.1.</strong> Updating LLVM</a></li><li class="chapter-item "><a href="backend/debugging.html"><strong aria-hidden="true">53.2.</strong> Debugging LLVM</a></li><li class="chapter-item "><a href="backend/backend-agnostic.html"><strong aria-hidden="true">53.3.</strong> Backend Agnostic Codegen</a></li><li class="chapter-item "><a href="backend/implicit-caller-location.html"><strong aria-hidden="true">53.4.</strong> Implicit Caller Location</a></li></ol></li><li class="chapter-item "><a href="backend/libs-and-metadata.html"><strong aria-hidden="true">54.</strong> Libraries and Metadata</a></li><li class="chapter-item "><a href="profile-guided-optimization.html"><strong aria-hidden="true">55.</strong> Profile-guided Optimization</a></li><li class="chapter-item "><a href="llvm-coverage-instrumentation.html"><strong aria-hidden="true">56.</strong> LLVM Source-Based Code Coverage</a></li><li class="chapter-item "><a href="sanitizers.html"><strong aria-hidden="true">57.</strong> Sanitizers Support</a></li><li class="chapter-item "><a href="debugging-support-in-rustc.html"><strong aria-hidden="true">58.</strong> Debugging Support in the Rust Compiler</a></li><li class="spacer"></li><li class="chapter-item affix "><a href="appendix/background.html">Appendix A: Background topics</a></li><li class="chapter-item affix "><a href="appendix/glossary.html">Appendix B: Glossary</a></li><li class="chapter-item affix "><a href="appendix/code-index.html">Appendix C: Code Index</a></li><li class="chapter-item affix "><a href="appendix/compiler-lecture.html">Appendix D: Compiler Lecture Series</a></li><li class="chapter-item affix "><a href="appendix/bibliography.html">Appendix E: Bibliography</a></li><li class="chapter-item affix "><a href="appendix/humorust.html">Appendix Z: HumorRust</a></li><li class="spacer"></li></ol>
</div>
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
</nav>
<div id="page-wrapper" class="page-wrapper">
<div class="page">
<div id="menu-bar-hover-placeholder"></div>
<div id="menu-bar" class="menu-bar sticky bordered">
<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 (default)</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">Guide to Rustc Development</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>
<a href="https://github.com/rust-lang/rustc-dev-guide" title="Git repository" aria-label="Git repository">
<i id="git-repository-button" class="fa fa-github"></i>
</a>
<a href="https://github.com/rust-lang/rustc-dev-guide/tree/master/src/macro-expansion.md?mode&#x3D;edit" title="Suggest an edit" aria-label="Suggest an edit">
<i id="git-edit-button" class="fa fa-edit"></i>
</a>
</div>
</div>
<div id="search-wrapper" class="hidden">
<form id="searchbar-outer" class="searchbar-outer">
<input type="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>
<h1 id="macro-expansion"><a class="header" href="#macro-expansion">Macro expansion</a></h1>
<ul>
<li><a href="#expansion-and-ast-integration">Expansion and AST Integration</a>
<ul>
<li><a href="#error-recovery">Error Recovery</a></li>
<li><a href="#name-resolution">Name Resolution</a></li>
<li><a href="#eager-expansion">Eager Expansion</a></li>
<li><a href="#other-data-structures">Other Data Structures</a></li>
</ul>
</li>
<li><a href="#hygiene-and-hierarchies">Hygiene and Hierarchies</a>
<ul>
<li><a href="#the-expansion-order-hierarchy">The Expansion Order Hierarchy</a></li>
<li><a href="#the-macro-definition-hierarchy">The Macro Definition Hierarchy</a></li>
<li><a href="#the-call-site-hierarchy">The Call-site Hierarchy</a></li>
<li><a href="#macro-backtraces">Macro Backtraces</a></li>
</ul>
</li>
<li><a href="#producing-macro-output">Producing Macro Output</a></li>
<li><a href="#macros-by-example">Macros By Example</a>
<ul>
<li><a href="#example">Example</a></li>
<li><a href="#the-mbe-parser">The MBE parser</a></li>
<li><a href="#macros-and-macros-20"><code>macro</code>s and Macros 2.0</a></li>
</ul>
</li>
<li><a href="#procedural-macros">Procedural Macros</a>
<ul>
<li><a href="#custom-derive">Custom Derive</a></li>
</ul>
</li>
</ul>
<blockquote>
<p><code>rustc_ast</code>, <code>rustc_expand</code>, and <code>rustc_builtin_macros</code> are all undergoing
refactoring, so some of the links in this chapter may be broken.</p>
</blockquote>
<p>Rust has a very powerful macro system. In the previous chapter, we saw how the
parser sets aside macros to be expanded (it temporarily uses <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_expand/placeholders/index.html">placeholders</a>).
This chapter is about the process of expanding those macros iteratively until
we have a complete AST for our crate with no unexpanded macros (or a compile
error).</p>
<p>First, we will discuss the algorithm that expands and integrates macro output
into ASTs. Next, we will take a look at how hygiene data is collected. Finally,
we will look at the specifics of expanding different types of macros.</p>
<p>Many of the algorithms and data structures described below are in <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_expand/index.html"><code>rustc_expand</code></a>,
with basic data structures in <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_expand/base/index.html"><code>rustc_expand::base</code></a>.</p>
<p>Also of note, <code>cfg</code> and <code>cfg_attr</code> are treated specially from other macros, and are
handled in <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_expand/config/index.html"><code>rustc_expand::config</code></a>.</p>
<h2 id="expansion-and-ast-integration"><a class="header" href="#expansion-and-ast-integration">Expansion and AST Integration</a></h2>
<p>First of all, expansion happens at the crate level. Given a raw source code for
a crate, the compiler will produce a massive AST with all macros expanded, all
modules inlined, etc. The primary entry point for this process is the
<a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_expand/expand/struct.MacroExpander.html#method.fully_expand_fragment"><code>MacroExpander::fully_expand_fragment</code></a> method. With few exceptions, we
use this method on the whole crate (see <a href="#eager-expansion">&quot;Eager Expansion&quot;</a>
below for more detailed discussion of edge case expansion issues).</p>
<p>At a high level, <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_expand/expand/struct.MacroExpander.html#method.fully_expand_fragment"><code>fully_expand_fragment</code></a> works in iterations. We keep a
queue of unresolved macro invocations (that is, macros we haven't found the
definition of yet). We repeatedly try to pick a macro from the queue, resolve
it, expand it, and integrate it back. If we can't make progress in an
iteration, this represents a compile error. Here is the <a href="https://github.com/rust-lang/rust/pull/53778#issuecomment-419224049">algorithm</a>:</p>
<ol start="0">
<li>Initialize an <code>queue</code> of unresolved macros.</li>
<li>Repeat until <code>queue</code> is empty (or we make no progress, which is an error):
<ol start="0">
<li><a href="./name-resolution.html">Resolve</a> imports in our partially built crate as
much as possible.</li>
<li>Collect as many macro <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_expand/expand/struct.Invocation.html"><code>Invocation</code>s</a> as possible from our
partially built crate (fn-like, attributes, derives) and add them to the
queue.</li>
<li>Dequeue the first element, and attempt to resolve it.</li>
<li>If it's resolved:
<ol start="0">
<li>Run the macro's expander function that consumes a <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/tokenstream/struct.TokenStream.html"><code>TokenStream</code></a> or
AST and produces a <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/tokenstream/struct.TokenStream.html"><code>TokenStream</code></a> or <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_expand/expand/enum.AstFragment.html"><code>AstFragment</code></a> (depending on
the macro kind). (A <code>TokenStream</code> is a collection of <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/tokenstream/enum.TokenTree.html"><code>TokenTree</code>s</a>,
each of which are a token (punctuation, identifier, or literal) or a
delimited group (anything inside <code>()</code>/<code>[]</code>/<code>{}</code>)).
<ul>
<li>At this point, we know everything about the macro itself and can
call <code>set_expn_data</code> to fill in its properties in the global data;
that is the hygiene data associated with <code>ExpnId</code>. (See <a href="#hygiene-and-hierarchies">the
&quot;Hygiene&quot; section below</a>).</li>
</ul>
</li>
<li>Integrate that piece of AST into the big existing partially built
AST. This is essentially where the &quot;token-like mass&quot; becomes a
proper set-in-stone AST with side-tables. It happens as follows:
<ul>
<li>If the macro produces tokens (e.g. a proc macro), we parse into
an AST, which may produce parse errors.</li>
<li>During expansion, we create <code>SyntaxContext</code>s (hierarchy 2). (See
<a href="#hygiene-and-hierarchies">the &quot;Hygiene&quot; section below</a>)</li>
<li>These three passes happen one after another on every AST fragment
freshly expanded from a macro:
<ul>
<li><a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/node_id/struct.NodeId.html"><code>NodeId</code></a>s are assigned by <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_expand/expand/struct.InvocationCollector.html"><code>InvocationCollector</code></a>. This
also collects new macro calls from this new AST piece and
adds them to the queue.</li>
<li><a href="https://rustc-dev-guide.rust-lang.org/hir.html?highlight=def,path#identifiers-in-the-hir">&quot;Def paths&quot;</a> are created and <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/def_id/struct.DefId.html"><code>DefId</code></a>s are
assigned to them by <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_resolve/def_collector/struct.DefCollector.html"><code>DefCollector</code></a>.</li>
<li>Names are put into modules (from the resolver's point of
view) by <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_resolve/build_reduced_graph/struct.BuildReducedGraphVisitor.html"><code>BuildReducedGraphVisitor</code></a>.</li>
</ul>
</li>
</ul>
</li>
<li>After expanding a single macro and integrating its output, continue
to the next iteration of <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_expand/expand/struct.MacroExpander.html#method.fully_expand_fragment"><code>fully_expand_fragment</code></a>.</li>
</ol>
</li>
<li>If it's not resolved:
<ol start="0">
<li>Put the macro back in the queue</li>
<li>Continue to next iteration...</li>
</ol>
</li>
</ol>
</li>
</ol>
<h3 id="error-recovery"><a class="header" href="#error-recovery">Error Recovery</a></h3>
<p>If we make no progress in an iteration, then we have reached a compilation
error (e.g. an undefined macro). We attempt to recover from failures
(unresolved macros or imports) for the sake of diagnostics. This allows
compilation to continue past the first error, so that we can report more errors
at a time. Recovery can't cause compilation to succeed. We know that it will
fail at this point. The recovery happens by expanding unresolved macros into
<a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/ast/enum.ExprKind.html#variant.Err"><code>ExprKind::Err</code></a>.</p>
<h3 id="name-resolution"><a class="header" href="#name-resolution">Name Resolution</a></h3>
<p>Notice that name resolution is involved here: we need to resolve imports and
macro names in the above algorithm. This is done in
<a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_resolve/macros/index.html"><code>rustc_resolve::macros</code></a>, which resolves macro paths, validates
those resolutions, and reports various errors (e.g. &quot;not found&quot; or &quot;found, but
it's unstable&quot; or &quot;expected x, found y&quot;). However, we don't try to resolve
other names yet. This happens later, as we will see in the <a href="./name-resolution.html">next
chapter</a>.</p>
<h3 id="eager-expansion"><a class="header" href="#eager-expansion">Eager Expansion</a></h3>
<p><em>Eager expansion</em> means that we expand the arguments of a macro invocation
before the macro invocation itself. This is implemented only for a few special
built-in macros that expect literals; expanding arguments first for some of
these macro results in a smoother user experience. As an example, consider the
following:</p>
<pre><code class="language-rust ignore">macro bar($i: ident) { $i }
macro foo($i: ident) { $i }
foo!(bar!(baz));
</code></pre>
<p>A lazy expansion would expand <code>foo!</code> first. An eager expansion would expand
<code>bar!</code> first.</p>
<p>Eager expansion is not a generally available feature of Rust. Implementing
eager expansion more generally would be challenging, but we implement it for a
few special built-in macros for the sake of user experience. The built-in
macros are implemented in <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_builtin_macros/index.html"><code>rustc_builtin_macros</code></a>, along with some other early
code generation facilities like injection of standard library imports or
generation of test harness. There are some additional helpers for building
their AST fragments in <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_expand/build/index.html"><code>rustc_expand::build</code></a>. Eager expansion generally
performs a subset of the things that lazy (normal) expansion. It is done by
invoking <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_expand/expand/struct.MacroExpander.html#method.fully_expand_fragment"><code>fully_expand_fragment</code></a> on only part of a crate (as opposed to
whole crate, like we normally do).</p>
<h3 id="other-data-structures"><a class="header" href="#other-data-structures">Other Data Structures</a></h3>
<p>Here are some other notable data structures involved in expansion and integration:</p>
<ul>
<li><a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_expand/base/trait.ResolverExpand.html"><code>ResolverExpand</code></a> - a trait used to break crate dependencies. This allows the
resolver services to be used in <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/index.html"><code>rustc_ast</code></a>, despite <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_resolve/index.html"><code>rustc_resolve</code></a> and
pretty much everything else depending on <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/index.html"><code>rustc_ast</code></a>.</li>
<li><a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_expand/base/struct.ExtCtxt.html"><code>ExtCtxt</code></a>/<a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_expand/base/struct.ExpansionData.html"><code>ExpansionData</code></a> - various intermediate data kept and used by expansion
infrastructure in the process of its work</li>
<li><a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_expand/base/enum.Annotatable.html"><code>Annotatable</code></a> - a piece of AST that can be an attribute target, almost same
thing as AstFragment except for types and patterns that can be produced by
macros but cannot be annotated with attributes</li>
<li><a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_expand/base/trait.MacResult.html"><code>MacResult</code></a> - a &quot;polymorphic&quot; AST fragment, something that can turn into a
different <code>AstFragment</code> depending on its <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_expand/expand/enum.AstFragmentKind.html"><code>AstFragmentKind</code></a> - item,
or expression, or pattern etc.</li>
</ul>
<h2 id="hygiene-and-hierarchies"><a class="header" href="#hygiene-and-hierarchies">Hygiene and Hierarchies</a></h2>
<p>If you have ever used C/C++ preprocessor macros, you know that there are some
annoying and hard-to-debug gotchas! For example, consider the following C code:</p>
<pre><code class="language-c">#define DEFINE_FOO struct Bar {int x;}; struct Foo {Bar bar;};
// Then, somewhere else
struct Bar {
...
};
DEFINE_FOO
</code></pre>
<p>Most people avoid writing C like this – and for good reason: it doesn't
compile. The <code>struct Bar</code> defined by the macro clashes names with the <code>struct Bar</code> defined in the code. Consider also the following example:</p>
<pre><code class="language-c">#define DO_FOO(x) {\
int y = 0;\
foo(x, y);\
}
// Then elsewhere
int y = 22;
DO_FOO(y);
</code></pre>
<p>Do you see the problem? We wanted to generate a call <code>foo(22, 0)</code>, but instead
we got <code>foo(0, 0)</code> because the macro defined its own <code>y</code>!</p>
<p>These are both examples of <em>macro hygiene</em> issues. <em>Hygiene</em> relates to how to
handle names defined <em>within a macro</em>. In particular, a hygienic macro system
prevents errors due to names introduced within a macro. Rust macros are hygienic
in that they do not allow one to write the sorts of bugs above.</p>
<p>At a high level, hygiene within the rust compiler is accomplished by keeping
track of the context where a name is introduced and used. We can then
disambiguate names based on that context. Future iterations of the macro system
will allow greater control to the macro author to use that context. For example,
a macro author may want to introduce a new name to the context where the macro
was called. Alternately, the macro author may be defining a variable for use
only within the macro (i.e. it should not be visible outside the macro).</p>
<p>The context is attached to AST nodes. All AST nodes generated by macros have
context attached. Additionally, there may be other nodes that have context
attached, such as some desugared syntax (non-macro-expanded nodes are
considered to just have the &quot;root&quot; context, as described below).
Throughout the compiler, we use <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/struct.Span.html"><code>rustc_span::Span</code>s</a> to refer to code locations.
This struct also has hygiene information attached to it, as we will see later.</p>
<p>Because macros invocations and definitions can be nested, the syntax context of
a node must be a hierarchy. For example, if we expand a macro and there is
another macro invocation or definition in the generated output, then the syntax
context should reflect the nesting.</p>
<p>However, it turns out that there are actually a few types of context we may
want to track for different purposes. Thus, there are not just one but <em>three</em>
expansion hierarchies that together comprise the hygiene information for a
crate.</p>
<p>All of these hierarchies need some sort of &quot;macro ID&quot; to identify individual
elements in the chain of expansions. This ID is <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/hygiene/struct.ExpnId.html"><code>ExpnId</code></a>. All macros receive
an integer ID, assigned continuously starting from 0 as we discover new macro
calls. All hierarchies start at <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/hygiene/struct.ExpnId.html#method.root"><code>ExpnId::root()</code></a>, which is its own
parent.</p>
<p><a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/hygiene/index.html"><code>rustc_span::hygiene</code></a> contains all of the hygiene-related algorithms
(with the exception of some hacks in <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_resolve/struct.Resolver.html#method.resolve_crate_root"><code>Resolver::resolve_crate_root</code></a>)
and structures related to hygiene and expansion that are kept in global data.</p>
<p>The actual hierarchies are stored in <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/hygiene/struct.HygieneData.html"><code>HygieneData</code></a>. This is a global
piece of data containing hygiene and expansion info that can be accessed from
any <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/symbol/struct.Ident.html"><code>Ident</code></a> without any context.</p>
<h3 id="the-expansion-order-hierarchy"><a class="header" href="#the-expansion-order-hierarchy">The Expansion Order Hierarchy</a></h3>
<p>The first hierarchy tracks the order of expansions, i.e., when a macro
invocation is in the output of another macro.</p>
<p>Here, the children in the hierarchy will be the &quot;innermost&quot; tokens. The
<a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/hygiene/struct.ExpnData.html"><code>ExpnData</code></a> struct itself contains a subset of properties from both macro
definition and macro call available through global data.
<a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/hygiene/struct.ExpnData.html#structfield.parent"><code>ExpnData::parent</code></a> tracks the child -&gt; parent link in this hierarchy.</p>
<p>For example,</p>
<pre><code class="language-rust ignore">macro_rules! foo { () =&gt; { println!(); } }
fn main() { foo!(); }
</code></pre>
<p>In this code, the AST nodes that are finally generated would have hierarchy:</p>
<pre><code>root
expn_id_foo
expn_id_println
</code></pre>
<h3 id="the-macro-definition-hierarchy"><a class="header" href="#the-macro-definition-hierarchy">The Macro Definition Hierarchy</a></h3>
<p>The second hierarchy tracks the order of macro definitions, i.e., when we are
expanding one macro another macro definition is revealed in its output. This
one is a bit tricky and more complex than the other two hierarchies.</p>
<p><a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/hygiene/struct.SyntaxContext.html"><code>SyntaxContext</code></a> represents a whole chain in this hierarchy via an ID.
<a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/hygiene/struct.SyntaxContextData.html"><code>SyntaxContextData</code></a> contains data associated with the given
<code>SyntaxContext</code>; mostly it is a cache for results of filtering that chain in
different ways. <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/hygiene/struct.SyntaxContextData.html#structfield.parent"><code>SyntaxContextData::parent</code></a> is the child -&gt; parent
link here, and <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/hygiene/struct.SyntaxContextData.html#structfield.outer_expn"><code>SyntaxContextData::outer_expns</code></a> are individual
elements in the chain. The &quot;chaining operator&quot; is
<a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/hygiene/struct.SyntaxContext.html#method.apply_mark"><code>SyntaxContext::apply_mark</code></a> in compiler code.</p>
<p>A <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/struct.Span.html"><code>Span</code></a>, mentioned above, is actually just a compact representation of
a code location and <code>SyntaxContext</code>. Likewise, an <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/symbol/struct.Ident.html"><code>Ident</code></a> is just an interned
<a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/symbol/struct.Symbol.html"><code>Symbol</code></a> + <code>Span</code> (i.e. an interned string + hygiene data).</p>
<p>For built-in macros, we use the context:
<code>SyntaxContext::empty().apply_mark(expn_id)</code>, and such macros are considered to
be defined at the hierarchy root. We do the same for proc-macros because we
haven't implemented cross-crate hygiene yet.</p>
<p>If the token had context <code>X</code> before being produced by a macro then after being
produced by the macro it has context <code>X -&gt; macro_id</code>. Here are some examples:</p>
<p>Example 0:</p>
<pre><code class="language-rust ignore">macro m() { ident }
m!();
</code></pre>
<p>Here <code>ident</code> originally has context <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/hygiene/struct.SyntaxContext.html#method.root"><code>SyntaxContext::root()</code></a>. <code>ident</code> has
context <code>ROOT -&gt; id(m)</code> after it's produced by <code>m</code>.</p>
<p>Example 1:</p>
<pre><code class="language-rust ignore">macro m() { macro n() { ident } }
m!();
n!();
</code></pre>
<p>In this example the <code>ident</code> has context <code>ROOT</code> originally, then <code>ROOT -&gt; id(m)</code>
after the first expansion, then <code>ROOT -&gt; id(m) -&gt; id(n)</code>.</p>
<p>Example 2:</p>
<p>Note that these chains are not entirely determined by their last element, in
other words <code>ExpnId</code> is not isomorphic to <code>SyntaxContext</code>.</p>
<pre><code class="language-rust ignore">macro m($i: ident) { macro n() { ($i, bar) } }
m!(foo);
</code></pre>
<p>After all expansions, <code>foo</code> has context <code>ROOT -&gt; id(n)</code> and <code>bar</code> has context
<code>ROOT -&gt; id(m) -&gt; id(n)</code>.</p>
<p>Finally, one last thing to mention is that currently, this hierarchy is subject
to the <a href="https://github.com/rust-lang/rust/pull/51762#issuecomment-401400732">&quot;context transplantation hack&quot;</a>. Basically, the more modern (and
experimental) <code>macro</code> macros have stronger hygiene than the older MBE system,
but this can result in weird interactions between the two. The hack is intended
to make things &quot;just work&quot; for now.</p>
<h3 id="the-call-site-hierarchy"><a class="header" href="#the-call-site-hierarchy">The Call-site Hierarchy</a></h3>
<p>The third and final hierarchy tracks the location of macro invocations.</p>
<p>In this hierarchy <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/hygiene/struct.ExpnData.html#structfield.call_site"><code>ExpnData::call_site</code></a> is the child -&gt; parent link.</p>
<p>Here is an example:</p>
<pre><code class="language-rust ignore">macro bar($i: ident) { $i }
macro foo($i: ident) { $i }
foo!(bar!(baz));
</code></pre>
<p>For the <code>baz</code> AST node in the final output, the first hierarchy is <code>ROOT -&gt; id(foo) -&gt; id(bar) -&gt; baz</code>, while the third hierarchy is <code>ROOT -&gt; baz</code>.</p>
<h3 id="macro-backtraces"><a class="header" href="#macro-backtraces">Macro Backtraces</a></h3>
<p>Macro backtraces are implemented in <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/index.html"><code>rustc_span</code></a> using the hygiene machinery
in <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/hygiene/index.html"><code>rustc_span::hygiene</code></a>.</p>
<h2 id="producing-macro-output"><a class="header" href="#producing-macro-output">Producing Macro Output</a></h2>
<p>Above, we saw how the output of a macro is integrated into the AST for a crate,
and we also saw how the hygiene data for a crate is generated. But how do we
actually produce the output of a macro? It depends on the type of macro.</p>
<p>There are two types of macros in Rust:
<code>macro_rules!</code> macros (a.k.a. &quot;Macros By Example&quot; (MBE)) and procedural macros
(or &quot;proc macros&quot;; including custom derives). During the parsing phase, the normal
Rust parser will set aside the contents of macros and their invocations. Later,
macros are expanded using these portions of the code.</p>
<p>Some important data structures/interfaces here:</p>
<ul>
<li><a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_expand/base/struct.SyntaxExtension.html"><code>SyntaxExtension</code></a> - a lowered macro representation, contains its expander
function, which transforms a <code>TokenStream</code> or AST into another <code>TokenStream</code>
or AST + some additional data like stability, or a list of unstable features
allowed inside the macro.</li>
<li><a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_expand/base/enum.SyntaxExtensionKind.html"><code>SyntaxExtensionKind</code></a> - expander functions may have several different
signatures (take one token stream, or two, or a piece of AST, etc). This is
an enum that lists them.</li>
<li><a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_expand/base/trait.ProcMacro.html"><code>ProcMacro</code></a>/<a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_expand/base/trait.TTMacroExpander.html"><code>TTMacroExpander</code></a>/<a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_expand/base/trait.AttrProcMacro.html"><code>AttrProcMacro</code></a>/<a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_expand/base/trait.MultiItemModifier.html"><code>MultiItemModifier</code></a> -
traits representing the expander function signatures.</li>
</ul>
<h2 id="macros-by-example"><a class="header" href="#macros-by-example">Macros By Example</a></h2>
<p>MBEs have their own parser distinct from the normal Rust parser. When macros
are expanded, we may invoke the MBE parser to parse and expand a macro. The
MBE parser, in turn, may call the normal Rust parser when it needs to bind a
metavariable (e.g. <code>$my_expr</code>) while parsing the contents of a macro
invocation. The code for macro expansion is in
<a href="https://github.com/rust-lang/rust/tree/master/compiler/rustc_expand/src/mbe"><code>compiler/rustc_expand/src/mbe/</code></a>.</p>
<h3 id="example"><a class="header" href="#example">Example</a></h3>
<p>It's helpful to have an example to refer to. For the remainder of this chapter,
whenever we refer to the &quot;example <em>definition</em>&quot;, we mean the following:</p>
<pre><code class="language-rust ignore">macro_rules! printer {
(print $mvar:ident) =&gt; {
println!(&quot;{}&quot;, $mvar);
};
(print twice $mvar:ident) =&gt; {
println!(&quot;{}&quot;, $mvar);
println!(&quot;{}&quot;, $mvar);
};
}
</code></pre>
<p><code>$mvar</code> is called a <em>metavariable</em>. Unlike normal variables, rather than
binding to a value in a computation, a metavariable binds <em>at compile time</em> to
a tree of <em>tokens</em>. A <em>token</em> is a single &quot;unit&quot; of the grammar, such as an
identifier (e.g. <code>foo</code>) or punctuation (e.g. <code>=&gt;</code>). There are also other
special tokens, such as <code>EOF</code>, which indicates that there are no more tokens.
Token trees resulting from paired parentheses-like characters (<code>(</code>...<code>)</code>,
<code>[</code>...<code>]</code>, and <code>{</code>...<code>}</code>) – they include the open and close and all the tokens
in between (we do require that parentheses-like characters be balanced). Having
macro expansion operate on token streams rather than the raw bytes of a source
file abstracts away a lot of complexity. The macro expander (and much of the
rest of the compiler) doesn't really care that much about the exact line and
column of some syntactic construct in the code; it cares about what constructs
are used in the code. Using tokens allows us to care about <em>what</em> without
worrying about <em>where</em>. For more information about tokens, see the
<a href="./the-parser.html">Parsing</a> chapter of this book.</p>
<p>Whenever we refer to the &quot;example <em>invocation</em>&quot;, we mean the following snippet:</p>
<pre><code class="language-rust ignore">printer!(print foo); // Assume `foo` is a variable defined somewhere else...
</code></pre>
<p>The process of expanding the macro invocation into the syntax tree
<code>println!(&quot;{}&quot;, foo)</code> and then expanding that into a call to <code>Display::fmt</code> is
called <em>macro expansion</em>, and it is the topic of this chapter.</p>
<h3 id="the-mbe-parser"><a class="header" href="#the-mbe-parser">The MBE parser</a></h3>
<p>There are two parts to MBE expansion: parsing the definition and parsing the
invocations. Interestingly, both are done by the macro parser.</p>
<p>Basically, the MBE parser is like an NFA-based regex parser. It uses an
algorithm similar in spirit to the <a href="https://en.wikipedia.org/wiki/Earley_parser">Earley parsing
algorithm</a>. The macro parser is
defined in <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_expand/mbe/macro_parser"><code>compiler/rustc_expand/src/mbe/macro_parser.rs</code></a>.</p>
<p>The interface of the macro parser is as follows (this is slightly simplified):</p>
<pre><code class="language-rust ignore">fn parse_tt(
parser: &amp;mut Cow&lt;Parser&gt;,
ms: &amp;[TokenTree],
) -&gt; NamedParseResult
</code></pre>
<p>We use these items in macro parser:</p>
<ul>
<li><code>parser</code> is a reference to the state of a normal Rust parser, including the
token stream and parsing session. The token stream is what we are about to
ask the MBE parser to parse. We will consume the raw stream of tokens and
output a binding of metavariables to corresponding token trees. The parsing
session can be used to report parser errors.</li>
<li><code>ms</code> a <em>matcher</em>. This is a sequence of token trees that we want to match
the token stream against.</li>
</ul>
<p>In the analogy of a regex parser, the token stream is the input and we are matching it
against the pattern <code>ms</code>. Using our examples, the token stream could be the stream of
tokens containing the inside of the example invocation <code>print foo</code>, while <code>ms</code>
might be the sequence of token (trees) <code>print $mvar:ident</code>.</p>
<p>The output of the parser is a <code>NamedParseResult</code>, which indicates which of
three cases has occurred:</p>
<ul>
<li>Success: the token stream matches the given matcher <code>ms</code>, and we have produced a binding
from metavariables to the corresponding token trees.</li>
<li>Failure: the token stream does not match <code>ms</code>. This results in an error message such as
&quot;No rule expected token <em>blah</em>&quot;.</li>
<li>Error: some fatal error has occurred <em>in the parser</em>. For example, this
happens if there are more than one pattern match, since that indicates
the macro is ambiguous.</li>
</ul>
<p>The full interface is defined <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_expand/mbe/macro_parser/fn.parse_tt.html">here</a>.</p>
<p>The macro parser does pretty much exactly the same as a normal regex parser with
one exception: in order to parse different types of metavariables, such as
<code>ident</code>, <code>block</code>, <code>expr</code>, etc., the macro parser must sometimes call back to the
normal Rust parser.</p>
<p>As mentioned above, both definitions and invocations of macros are parsed using
the macro parser. This is extremely non-intuitive and self-referential. The code
to parse macro <em>definitions</em> is in
<a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_expand/mbe/macro_rules"><code>compiler/rustc_expand/src/mbe/macro_rules.rs</code></a>. It defines the pattern for
matching for a macro definition as <code>$( $lhs:tt =&gt; $rhs:tt );+</code>. In other words,
a <code>macro_rules</code> definition should have in its body at least one occurrence of a
token tree followed by <code>=&gt;</code> followed by another token tree. When the compiler
comes to a <code>macro_rules</code> definition, it uses this pattern to match the two token
trees per rule in the definition of the macro <em>using the macro parser itself</em>.
In our example definition, the metavariable <code>$lhs</code> would match the patterns of
both arms: <code>(print $mvar:ident)</code> and <code>(print twice $mvar:ident)</code>. And <code>$rhs</code>
would match the bodies of both arms: <code>{ println!(&quot;{}&quot;, $mvar); }</code> and <code>{ println!(&quot;{}&quot;, $mvar); println!(&quot;{}&quot;, $mvar); }</code>. The parser would keep this
knowledge around for when it needs to expand a macro invocation.</p>
<p>When the compiler comes to a macro invocation, it parses that invocation using
the same NFA-based macro parser that is described above. However, the matcher
used is the first token tree (<code>$lhs</code>) extracted from the arms of the macro
<em>definition</em>. Using our example, we would try to match the token stream <code>print foo</code> from the invocation against the matchers <code>print $mvar:ident</code> and <code>print twice $mvar:ident</code> that we previously extracted from the definition. The
algorithm is exactly the same, but when the macro parser comes to a place in the
current matcher where it needs to match a <em>non-terminal</em> (e.g. <code>$mvar:ident</code>),
it calls back to the normal Rust parser to get the contents of that
non-terminal. In this case, the Rust parser would look for an <code>ident</code> token,
which it finds (<code>foo</code>) and returns to the macro parser. Then, the macro parser
proceeds in parsing as normal. Also, note that exactly one of the matchers from
the various arms should match the invocation; if there is more than one match,
the parse is ambiguous, while if there are no matches at all, there is a syntax
error.</p>
<p>For more information about the macro parser's implementation, see the comments
in <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_expand/mbe/macro_parser"><code>compiler/rustc_expand/src/mbe/macro_parser.rs</code></a>.</p>
<h3 id="macros-and-macros-20"><a class="header" href="#macros-and-macros-20"><code>macro</code>s and Macros 2.0</a></h3>
<p>There is an old and mostly undocumented effort to improve the MBE system, give
it more hygiene-related features, better scoping and visibility rules, etc. There
hasn't been a lot of work on this recently, unfortunately. Internally, <code>macro</code>
macros use the same machinery as today's MBEs; they just have additional
syntactic sugar and are allowed to be in namespaces.</p>
<h2 id="procedural-macros"><a class="header" href="#procedural-macros">Procedural Macros</a></h2>
<p>Procedural macros are also expanded during parsing, as mentioned above.
However, they use a rather different mechanism. Rather than having a parser in
the compiler, procedural macros are implemented as custom, third-party crates.
The compiler will compile the proc macro crate and specially annotated
functions in them (i.e. the proc macro itself), passing them a stream of tokens.</p>
<p>The proc macro can then transform the token stream and output a new token
stream, which is synthesized into the AST.</p>
<p>It's worth noting that the token stream type used by proc macros is <em>stable</em>,
so <code>rustc</code> does not use it internally (since our internal data structures are
unstable). The compiler's token stream is
<a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/tokenstream/struct.TokenStream.html"><code>rustc_ast::tokenstream::TokenStream</code></a>, as previously. This is
converted into the stable <a href="https://doc.rust-lang.org/proc_macro/struct.TokenStream.html"><code>proc_macro::TokenStream</code></a> and back in
<a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_expand/proc_macro/index.html"><code>rustc_expand::proc_macro</code></a> and <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_expand/proc_macro_server/index.html"><code>rustc_expand::proc_macro_server</code></a>.
Because the Rust ABI is unstable, we use the C ABI for this conversion.</p>
<p>TODO: more here. <a href="https://github.com/rust-lang/rustc-dev-guide/issues/1160">#1160</a></p>
<h3 id="custom-derive"><a class="header" href="#custom-derive">Custom Derive</a></h3>
<p>Custom derives are a special type of proc macro.</p>
<p>TODO: more? <a href="https://github.com/rust-lang/rustc-dev-guide/issues/1160">#1160</a></p>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="the-parser.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="name-resolution.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 rel="prev" href="the-parser.html" class="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="name-resolution.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 type="text/javascript">
window.playground_copyable = true;
</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>