Skip to content

Commit ff2f232

Browse files
committed
more notetaking
1 parent 8bbe1ff commit ff2f232

File tree

1 file changed

+34
-114
lines changed

1 file changed

+34
-114
lines changed

src/macro-expansion.md

Lines changed: 34 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -276,122 +276,65 @@ Primary structures:
276276
TODO: how a crate transitions from the state "macros exist as written in source" to "all macros are expanded"
277277
278278
Expansion Heirarchies and Syntax Context
279-
- Many AST nodes have some sort of syntax context, especially nodes from macros. The context 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.
279+
- Many AST nodes have some sort of syntax context, especially nodes from macros.
280+
- 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.
281+
- 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.
280282
- There are 3 expansion heirarchies
281283
- They all start at ExpnId::root, which is its own parent
284+
- 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.
285+
- There are vectors in `HygieneData` that contain expansion info.
286+
- There are entries here for both `SyntaxContext::empty()` and `ExpnId::root`, but they aren't used much.
282287
288+
1. Tracks expansion order: when a macro invocation is in the output of another macro.
289+
...
290+
expn_id2
291+
expn_id1
292+
InternalExpnData::parent is the child->parent link. That is the expn_id1 points to expn_id2 points to ...
283293
294+
Ex:
295+
macro_rules! foo { () => { println!(); } }
296+
fn main() { foo!(); }
284297
298+
// Then AST nodes that are finally generated would have parent(expn_id_println) -> parent(expn_id_foo), right?
285299
300+
2. Tracks macro definitions: when we are expanding one macro another macro definition is revealed in its output.
301+
...
302+
SyntaxContext2
303+
SyntaxContext1
304+
SyntaxContextData::parent is the child->parent link here.
305+
SyntaxContext is the whole chain in this hierarchy, and SyntaxContextData::outer_expns are individual elements in the chain.
286306
287307
288308
289-
# Discussion about hygiene
290-
291-
292-
```txt
293-
294-
295-
296-
Vadim Petrochenkov: All expansion hyerarchies (there are several of them) start
297-
at ExpnId::root.
298-
299-
Vadim Petrochenkov: Vectors in HygieneData has entries for both ctxt == 0 and
300-
expn_id == 0.
301-
302-
Vadim Petrochenkov: I don't think anyone looks into them much though.
303-
304-
Vadim Petrochenkov: Speaking of multiple hierarchies...
305-
306-
Vadim Petrochenkov: One is parent (expn_id1) -> parent(expn_id2) -> ...
307-
308-
Vadim Petrochenkov: This is the order in which macros are expanded.
309-
310-
Vadim Petrochenkov: Well.
311-
312-
Vadim Petrochenkov: When we are expanding one macro another macro is revealed
313-
in its output.
314-
315-
Vadim Petrochenkov: That's the parent-child relation in this hierarchy.
316-
317-
Vadim Petrochenkov: InternalExpnData::parent is the child->parent link.
318-
319-
mark-i-m: So in the above chain expn_id1 is the child?
320-
321-
Vadim Petrochenkov: Yes.
322-
323-
Vadim Petrochenkov: The second one is parent (SyntaxContext1) ->
324-
parent(SyntaxContext2) -> ...
325-
326-
Vadim Petrochenkov: This is about nested macro definitions. When we are
327-
expanding one macro another macro definition is revealed in its output.
328309
329-
Vadim Petrochenkov: SyntaxContextData::parent is the child->parent link here.
330310
331-
Vadim Petrochenkov: So, SyntaxContext is the whole chain in this hierarchy, and
332-
outer_expns are individual elements in the chain.
333-
334-
mark-i-m: So for example, suppose I have the following:
335-
336-
macro_rules! foo { () => { println!(); } }
337-
338-
fn main() { foo!(); }
339-
340-
Then AST nodes that are finally generated would have parent(expn_id_println) ->
341-
parent(expn_id_foo), right?
342-
343-
Vadim Petrochenkov: Pretty common construction (at least it was, before
344-
refactorings) is SyntaxContext::empty().apply_mark(expn_id), which means...
345-
346-
Vadim Petrochenkov:
347-
348-
Then AST nodes that are finally generated would have
349-
parent(expn_id_println) -> parent(expn_id_foo), right?
350-
351-
Yes.
311+
# Discussion about hygiene
352312
353-
mark-i-m:
354313
355-
and outer_expns are individual elements in the chain.
314+
```txt
356315
357-
Sorry, what is outer_expns?
358316
359-
Vadim Petrochenkov: SyntaxContextData::outer_expn
317+
Vadim Petrochenkov: Pretty common construction (at least it was, before refactorings) is SyntaxContext::empty().apply_mark(expn_id), which means a token produced by a built-in macro (which is defined in the root effectively).
360318
361-
Vadim Petrochenkov: ...which means a token produced by a built-in macro (which
362-
is defined in the root effectively).
319+
Vadim Petrochenkov: Or a stable proc macro, which are always considered to be defined in the root because they are always cross-crate, and we don't have the cross-crate hygiene implemented, ha-ha.
363320
364321
mark-i-m: Where does the expn_id come from?
365322
366-
Vadim Petrochenkov: Or a stable proc macro, which are always considered to be
367-
defined in the root because they are always cross-crate, and we don't have the
368-
cross-crate hygiene implemented, ha-ha.
369-
370-
Vadim Petrochenkov:
371-
372-
Where does the expn_id come from?
373-
374323
Vadim Petrochenkov: ID of the built-in macro call like line!().
375324
376-
Vadim Petrochenkov: Assigned continuously from 0 to N as soon as we discover
377-
new macro calls.
325+
Vadim Petrochenkov: Assigned continuously from 0 to N as soon as we discover new macro calls.
378326
379-
mark-i-m: Sorry, I didn't quite understand. Do you mean that only built-in
380-
macros receive continuous IDs?
327+
mark-i-m: Sorry, I didn't quite understand. Do you mean that only built-in macros receive continuous IDs?
381328
382-
Vadim Petrochenkov: So, the second hierarchy has a catch - the context
383-
transplantation hack -
384-
https://github.com/rust-lang/rust/pull/51762#issuecomment-401400732.
329+
Vadim Petrochenkov: So, the second hierarchy has a catch - the context transplantation hack - https://github.com/rust-lang/rust/pull/51762#issuecomment-401400732.
385330
386331
Vadim Petrochenkov:
387332
388333
Do you mean that only built-in macros receive continuous IDs?
389334
390335
Vadim Petrochenkov: No, all macro calls receive ID.
391336
392-
Vadim Petrochenkov: Built-ins have the typical pattern
393-
SyntaxContext::empty().apply_mark(expn_id) for syntax contexts produced by
394-
them.
337+
Vadim Petrochenkov: Built-ins have the typical pattern SyntaxContext::empty().apply_mark(expn_id) for syntax contexts produced by them.
395338
396339
mark-i-m: I see, but this pattern is only used for built-ins, right?
397340
@@ -407,23 +350,17 @@ Vadim Petrochenkov: but hierarchy 3 is root -> ident
407350
408351
Vadim Petrochenkov: ExpnInfo::call_site is the child-parent link in this case.
409352
410-
mark-i-m: When we expand, do we expand foo first or bar? Why is there a
411-
hierarchy 1 here? Is that foo expands first and it expands to something that
412-
contains bar!(ident)?
353+
mark-i-m: When we expand, do we expand foo first or bar? Why is there a hierarchy 1 here? Is that foo expands first and it expands to something that contains bar!(ident)?
413354
414355
Vadim Petrochenkov: Ah, yes, let's assume both foo and bar are identity macros.
415356
416-
Vadim Petrochenkov: Then foo!(bar!(ident)) -> expand -> bar!(ident) -> expand
417-
-> ident
357+
Vadim Petrochenkov: Then foo!(bar!(ident)) -> expand -> bar!(ident) -> expand -> ident
418358
419-
Vadim Petrochenkov: If bar were expanded first, that would be eager expansion -
420-
https://github.com/rust-lang/rfcs/pull/2320.
359+
Vadim Petrochenkov: If bar were expanded first, that would be eager expansion - https://github.com/rust-lang/rfcs/pull/2320.
421360
422-
mark-i-m: And after we expand only foo! presumably whatever intermediate state
423-
has heirarchy 1 of root->foo->(bar_ident), right?
361+
mark-i-m: And after we expand only foo! presumably whatever intermediate state has heirarchy 1 of root->foo->(bar_ident), right?
424362
425-
Vadim Petrochenkov: (We have it hacked into some built-in macros, but not
426-
generally.)
363+
Vadim Petrochenkov: (We have it hacked into some built-in macros, but not generally.)
427364
428365
Vadim Petrochenkov:
429366
@@ -432,23 +369,6 @@ generally.)
432369
433370
Vadim Petrochenkov: Yes.
434371
435-
mark-i-m: One last question: are there more hierarchies?
436-
437-
Vadim Petrochenkov: Not that I know of. Three + the context transplantation
438-
hack is already more complex than I'd like.
439-
440-
mark-i-m: Yes, one wonders what it would be like if one also had to think about
441-
eager expansion...
442-
443-
mark-i-m: so last time, we talked about the 3 context heirarchies
444-
445-
mark-i-m: Was there anything you wanted to add to that? If not, I think it
446-
would be good to get a big-picture... Given some piece of rust code, how do we
447-
get to the point where things are expanded and hygiene context is computed?
448-
449-
mark-i-m: (I'm assuming that hygiene info is computed as we expand stuff, since
450-
I don't think you can discover it beforehand)
451-
452372
Vadim Petrochenkov: Ok, let's move from hygiene to expansion.
453373
454374
Vadim Petrochenkov: Especially given that I don't remember the specific hygiene

0 commit comments

Comments
 (0)