8
8
// option. This file may not be copied, modified, or distributed
9
9
// except according to those terms.
10
10
11
- // Lowers the AST to the HIR
11
+ // Lowers the AST to the HIR.
12
+ //
13
+ // Since the AST and HIR are fairly similar, this is mostly a simple procedure,
14
+ // much like a fold. Where lowering involves a bit more work things get more
15
+ // interesting and there are some invariants you should know about. These mostly
16
+ // concern spans and ids.
17
+ //
18
+ // Spans are assigned to AST nodes during parsing and then are modified during
19
+ // expansion to indicate the origin of a node and the process it went through
20
+ // being expanded. Ids are assigned to AST nodes just before lowering.
21
+ //
22
+ // For the simpler lowering steps, ids and spans should be preserved. Unlike
23
+ // expansion we do not preserve the process of lowering in the spans, so spans
24
+ // should not be modified here. When creating a new node (as opposed to
25
+ // 'folding' an existing one), then you create a new id using `next_id()`.
26
+ //
27
+ // You must ensure that ids are unique. That means that you should only use the
28
+ // is from an AST node in a single HIR node (you can assume that AST node ids
29
+ // are unique). Every new node must have a unique id. Avoid cloning HIR nodes.
30
+ // If you do, you must then set one of the node's id to a fresh one.
31
+ //
32
+ // Lowering must be reproducable (the compiler only lowers once, but tools and
33
+ // custom lints may lower an AST node to a HIR node to interact with the
34
+ // compiler). The only interesting bit of this is ids - if you lower an AST node
35
+ // and create new HIR nodes with fresh ids, when re-lowering the same node, you
36
+ // must ensure you get the same ids! To do this, we keep track of the next id
37
+ // when we translate a node which requires new ids. By checking this cache and
38
+ // using node ids starting with the cached id, we ensure ids are reproducible.
39
+ // To use this system, you just need to hold on to a CachedIdSetter object
40
+ // whilst lowering. This is an RAII object that takes care of setting and
41
+ // restoring the cached id, etc.
42
+ //
43
+ // This whole system relies on node ids being incremented one at a time and
44
+ // all increments being for lowering. This means that you should not call any
45
+ // non-lowering function which will use new node ids.
46
+ //
47
+ // Spans are used for error messages and for tools to map semantics back to
48
+ // source code. It is therefore not as important with spans as ids to be strict
49
+ // about use (you can't break the compiler by screwing up a span). Obviously, a
50
+ // HIR node can only have a single span. But multiple nodes can have the same
51
+ // span and spans don't need to be kept in order, etc. Where code is preserved
52
+ // by lowering, it should have the same span as in the AST. Where HIR nodes are
53
+ // new it is probably best to give a span for the whole AST node being lowered.
54
+ // All nodes should have real spans, don't use dummy spans. Tools are likely to
55
+ // get confused if the spans from leaf AST nodes occur in multiple places
56
+ // in the HIR, especially for multiple identifiers.
12
57
13
58
use hir;
14
59
@@ -25,8 +70,12 @@ use std::cell::{Cell, RefCell};
25
70
26
71
pub struct LoweringContext < ' a > {
27
72
crate_root : Option < & ' static str > ,
73
+ // Map AST ids to ids used for expanded nodes.
28
74
id_cache : RefCell < HashMap < NodeId , NodeId > > ,
75
+ // Use if there are no cached ids for the current node.
29
76
id_assigner : & ' a NodeIdAssigner ,
77
+ // 0 == no cached id. Must be incremented to align with previous id
78
+ // incrementing.
30
79
cached_id : Cell < u32 > ,
31
80
}
32
81
0 commit comments