88// option. This file may not be copied, modified, or distributed
99// except according to those terms.
1010
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.
1257
1358use hir;
1459
@@ -25,8 +70,12 @@ use std::cell::{Cell, RefCell};
2570
2671pub struct LoweringContext < ' a > {
2772 crate_root : Option < & ' static str > ,
73+ // Map AST ids to ids used for expanded nodes.
2874 id_cache : RefCell < HashMap < NodeId , NodeId > > ,
75+ // Use if there are no cached ids for the current node.
2976 id_assigner : & ' a NodeIdAssigner ,
77+ // 0 == no cached id. Must be incremented to align with previous id
78+ // incrementing.
3079 cached_id : Cell < u32 > ,
3180}
3281
0 commit comments