liveBook · Manning

Type fragment specifier

As explained in Write Powerful Rust Macros

A type fragment specifier is a declarative-macro matcher specifier that matches Rust type syntax.

A type fragment specifier, written `ty`, matches Rust type syntax inside a declarative macro matcher. It lets a macro accept a caller-provided type, bind it to a metavariable, and reuse that type in generated code. section 2.4

Selecting the generated return type

A getter macro can provide a default `String` case and a second arm for other types: macro_rules! generate_get_value { ($struct_type:ident) => { generate_get_value!($struct_type, String); }; ($struct_type:ident, $return_type:ty) => { impl $struct_type { pub fn get_value(&self) -> &$return_type { &self.value } } } } `generate_get_value!(FirstName)` delegates to the `String` form, while `generate_get_value!(Age, i32)` captures `i32` with `ty` and inserts it into the generated method signature. section 2.2.3

Listing 2.9 Making it work for types other than Strings
struct Age {
    value: i32,
}

struct Pay {
    value: i32,
}

macro_rules! generate_get_value {
    ($struct_type:ident) => {
        impl $struct_type {
            pub fn get_value(&self) -> &String {
                &self.value
            }
        }
    };
    ($struct_type:ident,$return_type:ty) => { #1
        impl $struct_type {
            pub fn get_value(&self) -> &$return_type {
                &self.value
            }
        }
    }                 
}

generate_get_value!(FirstName);
generate_get_value!(LastName);
generate_get_value!(Age,i32);
generate_get_value!(Pay,i32);

Compare the two macro arms and their invocations for `String` and `i32`; the second arm shows the `ty` capture in context. section 2.2.3

How Write Powerful Rust Macros covers it

How deep it goes
Demonstrates matching and reusing a type through a working two-arm macro, without detailing the full grammar of Rust types.
Examples
Uses `generate_get_value!` with `FirstName`, `LastName`, `Age`, `String`, and `i32`.
What it assumes
Assumes Rust declarative-macro matcher syntax and introduces `ty` alongside `ident`, `expr`, `literal`, and `tt` alternatives.
What you can do after
Apply `ty` in `macro_rules!` definitions to accept caller-selected types and insert them into generated Rust signatures.
How it connects
Connects declarative macros with newtypes, macro matchers, generated methods, and type aliases.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Write Powerful Rust Macros. The section links point to the parts of the book it draws on.