dtolnay / proc-macro-workshop
Learn to write Rust procedural macros [Rust Latam conference, Montevideo Uruguay, March 2019]
AI Architecture Analysis
This repository is indexed by RepoMind. By analyzing dtolnay/proc-macro-workshop in our AI interface, you can instantly generate complete architecture diagrams, visualize control flows, and perform automated security audits across the entire codebase.
Our Agentic Context Augmented Generation (Agentic CAG) engine loads full source files into context on-demand, avoiding the fragmentation of traditional RAG systems. Ask questions about the architecture, dependencies, or specific features to see it in action.
Repository Overview (README excerpt)
Crawler viewRust Latam: procedural macros workshop *This repo contains a selection of projects designed to learn to write Rust procedural macros — Rust code that generates Rust code.* *Each of these projects is drawn closely from a compelling real use case. Out of the 5 projects here, 3 are macros that I have personally implemented in industrial codebases for work, and the other 2 exist as libraries on crates.io by other authors.* Contents • **Suggested prerequisites** • **Projects** — Introduction to each of the projects • **Derive macro:** • **Derive macro:** • **Function-like macro:** • **Attribute macro:** • **Attribute macro:** • **Project recommendations** — What to work on depending on your interests • **Test harness** — Explanation of how testing is set up • **Workflow** — Recommended way to work through the workshop • **Debugging tips** Suggested prerequisites This workshop covers attribute macros, derive macros, and function-like procedural macros. Be aware that the content of the workshop and the explanations in this repo will assume a working understanding of structs, enums, traits, trait impls, generic parameters, and trait bounds. You are welcome to dive into the workshop with any level of experience with Rust, but you may find that these basics are far easier to learn for the first time outside of the context of macros. Projects Here is an introduction to each of the projects. At the bottom, I give recommendations for what order to tackle them based on your interests. Note that each of these projects goes into more depth than what is described in the introduction here. Derive macro: This macro generates the boilerplate code involved in implementing the [builder pattern] in Rust. Builders are a mechanism for instantiating structs, especially structs with many fields, and especially if many of those fields are optional or the set of fields may need to grow backward compatibly over time. [builder pattern]: https://en.wikipedia.org/wiki/Builder_pattern There are a few different possibilities for expressing builders in Rust. Unless you have a strong pre-existing preference, to keep things simple for this project I would recommend following the example of the standard library's [ ] builder in which the setter methods each receive and return to allow chained method calls. [ ]: https://doc.rust-lang.org/std/process/struct.Command.html Callers will invoke the macro as follows. This project covers: • traversing syntax trees; • constructing output source code; • processing helper attributes to customize the generated code. *Project skeleton is located under the builder directory.* Derive macro: This macro implements a derive for the standard library [ ] trait that is more customizable than the similar derive macro exposed by the standard library. [ ]: https://doc.rust-lang.org/std/fmt/trait.Debug.html In particular, we'd like to be able to select the formatting used for individual struct fields by providing a format string in the style expected by Rust string formatting macros like and . Here, one possible instance of the struct above might be printed by its generated impl like this: This project covers: • traversing syntax trees; • constructing output source code; • processing helper attributes; • dealing with lifetime parameters and type parameters; • inferring trait bounds on generic parameters of trait impls; • limitations of derive's ability to emit universally correct trait bounds. *Project skeleton is located under the debug directory.* Function-like macro: This macro provides a syntax for stamping out sequentially indexed copies of an arbitrary chunk of code. For example our application may require an enum with sequentially numbered variants like ... . But note that the same macro should work for any sort of compile-time loop; there is nothing specific to emitting enum variants. A different caller might use it for generating an expression like . This project covers: • parsing custom syntax; • low-level representation of token streams; • constructing output source code. *Project skeleton is located under the seq directory.* Attribute macro: A macro for when your coworkers (or you yourself) cannot seem to keep enum variants in sorted order when adding variants or refactoring. The macro will detect unsorted variants at compile time and emit an error pointing out which variants are out of order. This project covers: • compile-time error reporting; • application of visitor pattern to traverse a syntax tree; • limitations of the currently stable macro API and some ways to work around them. *Project skeleton is located under the sorted directory.* Attribute macro: This macro provides a mechanism for defining structs in a packed binary representation with access to ranges of bits, similar to the language-level support for [bit fields in C]. [bit fields in C]: https://en.cppreference.com/w/cpp/language/bit_field The macro will conceptualize one of these structs as a sequence of bits 0..N. The bits are grouped into fields in the order specified by a struct written by the caller. The attribute rewrites the caller's struct into a private byte array representation with public getter and setter methods for each field. The total number of bits N is required to be a multiple of 8 (this will be checked at compile time). For example, the following invocation builds a struct with a total size of 32 bits or 4 bytes. It places field in the least significant bit of the first byte, field in the next three least significant bits, field in the remaining four most significant bits of the first byte, and field spanning the next three bytes. The code emitted by the macro for this struct would be as follows. Note that the field getters and setters use whichever of , , , is the smallest while being at least as large as the number of bits in the field. This project covers: • traversing syntax trees; • processing helper attributes; • constructing output source code; • in…