Skip to content

Commit aacadcf

Browse files
committed
Add common patterns section
1 parent dd56572 commit aacadcf

File tree

1 file changed

+88
-2
lines changed

1 file changed

+88
-2
lines changed

text/0000-pub-macro-rules.md

+88-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
- Feature Name: `pub_macro_rules`
2-
- Start Date: 2021-01-25
1+
- Feature Name: `macro_rules_visibility_v3`
2+
- Start Date: 2021-01-07
33
- RFC PR: [rust-lang/rfcs#0000](https://github.com/rust-lang/rfcs/pull/0000)
44
- Rust Issue: [rust-lang/rust#0000](https://github.com/rust-lang/rust/issues/0000)
55

@@ -91,6 +91,7 @@ To migrate to a path scoping visibility system the following would need to be up
9191
* publicly re-export them from the top-level module of the crate where the macro is defined
9292
* Remove `#[macro_use]` where annotating a module
9393
* mark all the macros in the previously annotated module as `pub(crate)`
94+
* mark the module itself as pub(crate) if not already `pub(crate)` or `pub`
9495
* annotate the macro invocation with a path to the module where the macro is defined.
9596
* Remove `#[macro_use]` from from `extern crate` item
9697
* change all uses of macros to qualified `$EXTERNAL_CRATE::$MACRO_NAME` invocations.
@@ -99,6 +100,91 @@ These steps should be automatable so that rustfix can be used to aid in migratio
99100

100101
Roughly what percentage of use cases will be machine migratable is an open question.
101102

103+
## Translating Common Patterns
104+
105+
The following are how common patterns in macros today translate to the next path based scoping system.
106+
107+
### Deeply nested macros
108+
109+
Macro use makes all macros inside a child module available to the parent module.
110+
111+
```rust
112+
113+
#[macro_use]
114+
mod m {
115+
#[macro_use]
116+
mod n {
117+
macro_rules! define_foo { () => { fn foo() {} } }
118+
}
119+
}
120+
121+
122+
define_foo!();
123+
```
124+
125+
This would be translated as:
126+
127+
```rust
128+
pub(crate) mod m {
129+
pub(crate) mod n {
130+
pub(crate) macro_rules! define_foo { () => { fn foo() {} } }
131+
}
132+
}
133+
134+
135+
m::n::define_foo!();
136+
```
137+
138+
### Recursive macros
139+
140+
Recursive macros are macros that call themselves (perhaps with different arguments)
141+
142+
```rust
143+
#[macro_use]
144+
mod m {
145+
macro_rules! print_expr {
146+
($e:expr) => {{
147+
println!("Going to do {}", stringify!($e));
148+
print_expr!(no_print => $e)
149+
}};
150+
(no_print => $e:expr) => {{
151+
$e
152+
}};
153+
}
154+
}
155+
156+
fn main() {
157+
print_expr!(1 + 1)
158+
}
159+
```
160+
161+
Naively changing this to path based scope would not work as it is not guaranteed that the unqualified `print_expr` name is in scope. In the example above, `print_expr!` is used recursively inside the macro, but in a path scoped system the recursive call would not be in scope if the macro was called with a qualified path (e.g., user calls `m::print_expr!` which references unqualified `print_expr!` which is not in scope).
162+
163+
TODO: Describe how we'll handle this
164+
165+
### "Private" macros
166+
167+
Macros can use "private" macros (i.e., macros defined inside of other macros).
168+
169+
```rust
170+
macro_rules! foo {
171+
($o:expr) => {{
172+
macro_rules! __helper {
173+
($e:expr) => {{
174+
println!("Expression: {}", stringify!($e));
175+
$e
176+
}};
177+
}
178+
179+
__helper!($o)
180+
}};
181+
}
182+
```
183+
184+
Naively changing this
185+
186+
TODO: Describe how we'll handle this
187+
102188
# Guide-level explanation
103189

104190
[guide-level-explanation]: #guide-level-explanation

0 commit comments

Comments
 (0)