Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions code/examples/misc_7.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
macro_rules! capture {
($e:expr) => {
transform!($e)
};
}

macro_rules! transform {
($a:tt + $b:tt) => {
$a * $b
};
($other:expr) => {
$other
};
}

fn main() {
let x = capture!(2 + 3);
println!("{}", x); // what this will print?
}
1 change: 1 addition & 0 deletions src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
- [Miscellaneous 4](./misc/4.md)
- [Miscellaneous 5](./misc/5.md)
- [Miscellaneous 6](./misc/6.md)
- [Miscellaneous 7](./misc/7.md)
- [Miscellaneous 8](./misc/8.md)
- [Miscellaneous 9](./misc/9.md)
- [Miscellaneous 10](./misc/10.md)
Expand Down
21 changes: 18 additions & 3 deletions src/misc/7.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
<!--
# Misc 7 @Kivooeo

try to destructure a captured metavariable into its token parts in a macro rules matcher, which does not work
{{#include ../include/quiz-is-wip.md}}

-->
```rust
{{#include ../../code/examples/misc_7.rs}}
```

<details>
<summary>Solution</summary>

It will prints `5`.

Once a token is captured as an expression (`:expr`), it becomes opaque to macro pattern matching and cannot be destructured into its component tokens.

When `capture!(2 + 3)` is invoked, the `$e:expr` matcher captures `2 + 3` as a single expression token tree. This captured expression is then passed to `transform!($e)`, which attempts to match it against the pattern `$a:tt + $b:tt`.

However, because `$e` was already captured as an `:expr`, it cannot be pattern-matched as separate tokens anymore. The first arm `$a:tt + $b:tt` fails to match, so the second arm `$other:expr` matches instead, and the expression `2 + 3` is returned as-is, evaluating to `5`.

</details>