Macro that receives the entire crate as a TokenStream

You can do something like this:

#[duration_units]
fn foo() -> Duration {
    30min + 20sec * 3
}

Let's say you wanted to use this syntax everywhere in your crate. You would have to annotate every function with this attribute!

Inner attributes make life a little easier. You could have a #![duration_units] and put it at the top of every module. Then it just applies the same transformation

What about if you didnt even need to do that? What if we had "Crate macros" that receive the entire crate as a single TokenStream and transformed it into another TokenStream

Does anyone know if it's possible to hack this with e.g. build.rs or something? Not sure if that's possible but worth thinking about - if anyone has some ideas.

With crate macros you could fully extend Rust's syntax in very interesting ways - e.g. adding custom literals (as much as the parser allows it, so no custom operators)

there's an highly unstable feature called custom_inner_attributes, but there are many open questions not solved, read the tracking issue for details.

You can do code generation from build scripts. This is how protobuf-codegen generates Rust types from a protobuf file, for example.

I read through the tracking issue, it seems like the main blocker is ambiguity in path resolution. So maybe it'd be worth to try stabilize the feature with absolute path inner attribute macros only?

// accepted
#![::some::macr]
// compile error: inner attribute macro must be an absolute path
#![some::macr]

The idea is that you write a function like this

fn a() -> Duration {
    10min + 4sec
}

assert_eq!(a(), Duration::from_mins(10) + Duration::from_secs(4));

And it'll compile. How would this be accomplished in a build script? I guess the build script can generate the same function with the literals properly replaced:

fn a() -> Duration {
    Duration::from_min(10) + Duration::from_sec(4)
}

assert_eq!(a(), Duration::from_mins(10) + Duration::from_secs(4));

Then you'd include!() the file. But you'll then have 2 copies of a, instead of what we want: a itself being modified

I don't think you can do in-place modifications to the source of your crate from a build script. There is no way to revert the file back to the original source with your custom literals post compilation. But maybe a custom xtask could be a viable solution. That is, if we are talking about a custom solution for a concrete project (or a PoC for custom literals) and not about a general, ergonomic and built-in solution, as there isn't one at the moment (i.e. no stable inner attribute proc macros).

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.