You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The context is attached to AST nodes. All AST nodes generated by macros have
167
+
context attached. Additionally, there may be other nodes that have context
168
+
attached, such as some desugared syntax (non-macro-expanded nodes are
169
+
considered to just have the "root" context, as described below).
167
170
168
-
- Many AST nodes have some sort of syntax context, especially nodes from macros.
169
-
- When we ask what is the syntax context of a node, the answer actually differs by what we are trying to do. Thus, we don't just keep track of a single context. There are in fact 3 different types of context used for different things.
170
-
- Each type of context is tracked by an "expansion heirarchy". As we expand macros, new macro calls or macro definitions may be generated, leading to some nesting. This nesting is where the heirarchies come from. Each heirarchy tracks some different aspect, though, as we will see.
171
-
- There are 3 expansion heirarchies
172
-
- All macros receive an integer ID assigned continuously starting from 0 as we discover new macro calls
173
-
- This is used as the `expn_id` where needed.
174
-
- All heirarchies start at ExpnId::root, which is its own parent
175
-
- The context of a node consists of a chain of expansions leading to `ExpnId::root`. A non-macro-expanded node has syntax context 0 (`SyntaxContext::empty()`) which represents just the root node.
176
-
- There are vectors in `HygieneData` that contain expansion info.
177
-
- There are entries here for both `SyntaxContext::empty()` and `ExpnId::root`, but they aren't used much.
171
+
Because macros invocations and definitions can be nested, the syntax context of
172
+
a node must be a heirarchy. For example, if we expand a macro and there is
173
+
another macro invocation or definition in the generated output, then the syntax
174
+
context should reflex the nesting.
178
175
179
-
1. Tracks expansion order: when a macro invocation is in the output of another macro.
180
-
...
181
-
expn_id2
182
-
expn_id1
183
-
InternalExpnData::parent is the child->parent link. That is the expn_id1 points to expn_id2 points to ...
176
+
However, it turns out that there are actually a few types of context we may
177
+
want to track for different purposes. Thus, there not just one but _three_
178
+
expansion heirarchies that together comprise the hygiene information for a
179
+
crate.
184
180
185
-
Ex:
186
-
macro_rules! foo { () => { println!(); } }
187
-
fn main() { foo!(); }
181
+
All of these heirarchies need some sort of "macro ID" to identify individual
182
+
elements in the chain of expansions. This ID is [`ExpnId`]. All macros receive
183
+
an integer ID, assigned continuously starting from 0 as we discover new macro
184
+
calls. All heirarchies start at [`ExpnId::root()`][rootid], which is its own
185
+
parent.
188
186
189
-
// Then AST nodes that are finally generated would have parent(expn_id_println) -> parent(expn_id_foo), right?
187
+
The actual heirarchies are stored in [`HygieneData`][hd], and all of the
188
+
hygiene-related algorithms are implemented in [`rustc_span::hygiene`][hy], with
189
+
the exception of some hacks [`Resolver::resolve_crate_root`][hacks].
190
190
191
-
2. Tracks macro definitions: when we are expanding one macro another macro definition is revealed in its output.
192
-
...
193
-
SyntaxContext2
194
-
SyntaxContext1
195
-
SyntaxContextData::parent is the child->parent link here.
196
-
SyntaxContext is the whole chain in this hierarchy, and SyntaxContextData::outer_expns are individual elements in the chain.
- For built-in macros (e.g. `line!()`) or stable proc macros: tokens produced by the macro are given the context `SyntaxContext::empty().apply_mark(expn_id)`
199
-
- Such macros are considered to have been defined at the root.
200
-
- For proc macros this is because they are always cross-crate and we don't have cross-crate hygiene implemented.
197
+
### The Expansion Order Heirarchy
201
198
202
-
The second hierarchy has the context transplantation hack. See https://github.com/rust-lang/rust/pull/51762#issuecomment-401400732.
199
+
The first heirarchy tracks the order of expansions, i.e., when a macro
200
+
invocation is in the output of another macro.
203
201
204
-
If the token had context X before being produced by a macro then after being produced by the macro it has context X -> macro_id.
202
+
Here, the children in the heirarchy will be the "innermost" tokens.
203
+
[`ExpnData::parent`][edp] tracks the child -> parent link in this heirarchy.
0 commit comments