Postfix macros is the feature proposal that would allow something.macro!(x, y, z). It’s been stalled for a long time on some design issues; in this blog post I’m exploring an idea that could answer these issues. The obvious way to make the feature work is to say that in <expr>.macro!(), the macro gets the tokens for <expr> and does what it wants with them. This however allows macros to break the so-called “no-backtracking rule” (coined by Tyler Mandry IIRC): in x.is_some().while! { ... }, reading the while makes us realize that the is_some() call wasn’t just a boolean value, it was an expression to be evaluated every loop. So we sort of have to go back and re-read the beginning of the line. For purposes of reducing surprise and code legibility, we’d like to avoid that. Hence the question that the feature stalled on: can we design postfix macros that always respect the no-backtracking rule? We would need to somehow evaluate <expr> once and pass the result to the macro instead of passing <expr> itself. Apart from that I’ll assume that we want maximal expressiveness. This post is centrally about places and the implicit operations that surround them; check out my recent blog post on the topic for an overview of that vocabulary. Partial Place Evaluation To get the obvious out of the way: we can’t just desugar <expr>.method() to let x = <expr>; x.method(); that may give entirely the wrong behavior, e.g.: struct Foo { count: Option<u32> } impl Foo { fn take_count(&mut self) -> Option<u32> { // That's fine self.count.take() // That creates a copy // let tmp = self.count; // tmp.take() // modifies the copy instead of the original } } In technical terms, that’s because the LHS of a method call is a place expression. Storing <expr> in a temporary adds an incorrect place-to-value coercion. The same applies to postfix macros. I think that the behavior we ideally want is to pre-evaluate all temporaries (that arise from value-to-place coercion), and pass whatever remains of the ex...
First seen: 2025-12-19 22:19
Last seen: 2025-12-19 22:19