1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
use rustc::hir::intravisit::{Visitor, NestedVisitorMap};
use isolated_encoder::IsolatedEncoder;
use schema::*;
use rustc::hir;
use rustc::ty::{self, TyCtxt};
use rustc::ich::Fingerprint;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
#[derive(RustcEncodable, RustcDecodable)]
pub struct Ast<'tcx> {
pub body: Lazy<hir::Body>,
pub tables: Lazy<ty::TypeckTables<'tcx>>,
pub nested_bodies: LazySeq<hir::Body>,
pub rvalue_promotable_to_static: bool,
pub stable_bodies_hash: Fingerprint,
}
impl_stable_hash_for!(struct Ast<'tcx> {
body,
tables,
nested_bodies,
rvalue_promotable_to_static,
stable_bodies_hash
});
impl<'a, 'b, 'tcx> IsolatedEncoder<'a, 'b, 'tcx> {
pub fn encode_body(&mut self, body_id: hir::BodyId) -> Lazy<Ast<'tcx>> {
let body = self.tcx.hir.body(body_id);
let stable_bodies_hash = {
let mut hcx = self.tcx.create_stable_hashing_context();
let mut hasher = StableHasher::new();
hcx.while_hashing_hir_bodies(true, |hcx| {
body.hash_stable(hcx, &mut hasher);
});
hasher.finish()
};
let lazy_body = self.lazy(body);
let body_owner_def_id = self.tcx.hir.body_owner_def_id(body_id);
let tables = self.tcx.typeck_tables_of(body_owner_def_id);
let lazy_tables = self.lazy(tables);
let mut visitor = NestedBodyCollector {
tcx: self.tcx,
bodies_found: Vec::new(),
};
visitor.visit_body(body);
let lazy_nested_bodies = self.lazy_seq_ref_from_slice(&visitor.bodies_found);
let rvalue_promotable_to_static =
self.tcx.const_is_rvalue_promotable_to_static(body_owner_def_id);
self.lazy(&Ast {
body: lazy_body,
tables: lazy_tables,
nested_bodies: lazy_nested_bodies,
rvalue_promotable_to_static,
stable_bodies_hash,
})
}
}
struct NestedBodyCollector<'a, 'tcx: 'a> {
tcx: TyCtxt<'a, 'tcx, 'tcx>,
bodies_found: Vec<&'tcx hir::Body>,
}
impl<'a, 'tcx: 'a> Visitor<'tcx> for NestedBodyCollector<'a, 'tcx> {
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
NestedVisitorMap::None
}
fn visit_nested_body(&mut self, body: hir::BodyId) {
let body = self.tcx.hir.body(body);
self.bodies_found.push(body);
self.visit_body(body);
}
}