Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to write something as complex as `print!` in a pure Rust macro?

I am starting out learning Rust macros, but the documentation is somewhat limited. Which is fine — they're an expert feature, I guess. While I can do basic code generation, implementation of traits, and so on, some of the built-in macros seem well beyond that, such as the various print macros, which examine a string literal and use that for code expansion.

I looked at the source for print! and it calls another macro called format_args. Unfortunately this doesn't seem to be built in "pure Rust" the comment just says "compiler built-in."

Is it possible to write something as complex as print! in a pure Rust macro? If so, how would it be done?

I'm actually interested in building a "compile time trie" -- basically recognizing certain fixed strings as "keywords" fixed at compile time. This would be performant (probably) but mostly I'm just interested in code generation.

like image 993
Richard Rast Avatar asked May 26 '18 18:05

Richard Rast


Video Answer


2 Answers

format_args is implemented in the compiler itself, in the libsyntax_ext crate. The name is registered in the register_builtins function, and the code to process it has its entry point in the expand_format_args function.

Macros that do such detailed syntax processing cannot be defined using the macro_rules! construct. They can be defined with a procedural macro; however, this feature is currently unstable (can only be used with the nightly compiler and is subject to sudden and unannounced changes) and rather sparsely documented.

like image 137
Sebastian Redl Avatar answered Sep 23 '22 13:09

Sebastian Redl


Rust macros cannot parse string literals, so it's not possible to create a direct Rust equivalent of format_args!.

What you could do is to use a macro to transform the function-call-like syntax into something that represents the variadic argument list in the Rust type system in some way (say, as a heterogeneous single-linked list, or a builder type). This can then be passed to a regular Rust function, along with the format string. But you will not be able to implement compile-time type checking of the format string this way.

like image 23
Florian Weimer Avatar answered Sep 20 '22 13:09

Florian Weimer