Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Literal syntax and external modules

API reference on docs.rs: literally_literal_string!, expand!, excluded_macros.

literally_literal_string!

literally_literal_string! turns @@"text" into an owned String:

You write Roughly expands to
let greeting: String = literally_literal_string!(@@"hello");
assert_eq!(greeting, "hello");
let greeting: String = ::std::string::String::from("hello");
assert_eq!(greeting, "hello");

That spelling is not valid ordinary Rust. It works inside a function-like macro because rustc gives the macro its input tokens before parsing them as an expression.

expand!

At item level, invalid syntax must live in a separate file so rustc does not parse it first. expand! loads an out-of-line module and wraps its body in the selected rewriting macros.

You write Roughly expands to
expand!(
    literally_literal_string;
    mod experiments;
);

// experiments.rs
pub fn greeting() -> String {
    @@"hello from inadvisable Rust"
}
mod experiments {
    pub fn greeting() -> String {
        ::std::string::String::from(
            "hello from inadvisable Rust",
        )
    }
}

Multiple macro paths are applied in their written order. expand! currently loads one module file; it does not recursively load out-of-line child modules. Cargo may also miss a change made only to a file read by the procedural macro, so force a rebuild if an edit appears to be ignored.

Excluding macro inputs

Some macros own private token syntax that another transformation must not touch. Configure exact macro names in expand!:

You write Roughly expands to
expand!(
    literally_literal_string,
    exclude_macros = (raw_tokens);
    mod experiments;
);

// experiments.rs
raw_tokens!(@@"untouched");
let text = @@"rewritten";
mod experiments {
    raw_tokens!(@@"untouched");
    let text = ::std::string::String::from("rewritten");
}

The excluded_macros attribute provides the same configuration when wrapping a configuration-aware item-position transformation.