]> git.lizzy.rs Git - rust.git/blob - src/librustc_incremental/persist/directory.rs
Rollup merge of #41135 - japaric:unstable-docs, r=steveklabnik
[rust.git] / src / librustc_incremental / persist / directory.rs
1 // Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 //! Code to convert a DefId into a DefPath (when serializing) and then
12 //! back again (when deserializing). Note that the new DefId
13 //! necessarily will not be the same as the old (and of course the
14 //! item might even be removed in the meantime).
15
16 use rustc::dep_graph::DepNode;
17 use rustc::hir::map::DefPath;
18 use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
19 use rustc::ty::TyCtxt;
20 use rustc::util::nodemap::DefIdMap;
21 use std::fmt::{self, Debug};
22 use std::iter::once;
23 use std::collections::HashMap;
24
25 /// Index into the DefIdDirectory
26 #[derive(Copy, Clone, Debug, PartialOrd, Ord, Hash, PartialEq, Eq,
27          RustcEncodable, RustcDecodable)]
28 pub struct DefPathIndex {
29     index: u32
30 }
31
32 #[derive(RustcEncodable, RustcDecodable)]
33 pub struct DefIdDirectory {
34     // N.B. don't use Removable here because these def-ids are loaded
35     // directly without remapping, so loading them should not fail.
36     paths: Vec<DefPath>,
37
38     // For each crate, saves the crate-name/disambiguator so that
39     // later we can match crate-numbers up again.
40     krates: Vec<CrateInfo>,
41 }
42
43 #[derive(Debug, RustcEncodable, RustcDecodable)]
44 pub struct CrateInfo {
45     krate: CrateNum,
46     name: String,
47     disambiguator: String,
48 }
49
50 impl DefIdDirectory {
51     pub fn new(krates: Vec<CrateInfo>) -> DefIdDirectory {
52         DefIdDirectory { paths: vec![], krates: krates }
53     }
54
55     fn max_current_crate(&self, tcx: TyCtxt) -> CrateNum {
56         tcx.sess.cstore.crates()
57                        .into_iter()
58                        .max()
59                        .unwrap_or(LOCAL_CRATE)
60     }
61
62     /// Returns a string form for `index`; useful for debugging
63     pub fn def_path_string(&self, tcx: TyCtxt, index: DefPathIndex) -> String {
64         let path = &self.paths[index.index as usize];
65         if self.krate_still_valid(tcx, self.max_current_crate(tcx), path.krate) {
66             path.to_string(tcx)
67         } else {
68             format!("<crate {} changed>", path.krate)
69         }
70     }
71
72     pub fn krate_still_valid(&self,
73                              tcx: TyCtxt,
74                              max_current_crate: CrateNum,
75                              krate: CrateNum) -> bool {
76         // Check that the crate-number still matches. For now, if it
77         // doesn't, just return None. We could do better, such as
78         // finding the new number.
79
80         if krate > max_current_crate {
81             false
82         } else {
83             let old_info = &self.krates[krate.as_usize()];
84             assert_eq!(old_info.krate, krate);
85             let old_name: &str = &old_info.name;
86             let old_disambiguator: &str = &old_info.disambiguator;
87             let new_name: &str = &tcx.crate_name(krate).as_str();
88             let new_disambiguator: &str = &tcx.crate_disambiguator(krate).as_str();
89             old_name == new_name && old_disambiguator == new_disambiguator
90         }
91     }
92
93     pub fn retrace(&self, tcx: TyCtxt) -> RetracedDefIdDirectory {
94
95         fn make_key(name: &str, disambiguator: &str) -> String {
96             format!("{}/{}", name, disambiguator)
97         }
98
99         let new_krates: HashMap<_, _> =
100             once(LOCAL_CRATE)
101             .chain(tcx.sess.cstore.crates())
102             .map(|krate| (make_key(&tcx.crate_name(krate).as_str(),
103                                    &tcx.crate_disambiguator(krate).as_str()), krate))
104             .collect();
105
106         let ids = self.paths.iter()
107                             .map(|path| {
108                                 let old_krate_id = path.krate.as_usize();
109                                 assert!(old_krate_id < self.krates.len());
110                                 let old_crate_info = &self.krates[old_krate_id];
111                                 let old_crate_key = make_key(&old_crate_info.name,
112                                                          &old_crate_info.disambiguator);
113                                 if let Some(&new_crate_key) = new_krates.get(&old_crate_key) {
114                                     tcx.retrace_path(new_crate_key, &path.data)
115                                 } else {
116                                     debug!("crate {:?} no longer exists", old_crate_key);
117                                     None
118                                 }
119                             })
120                             .collect();
121         RetracedDefIdDirectory { ids: ids }
122     }
123 }
124
125 #[derive(Debug, RustcEncodable, RustcDecodable)]
126 pub struct RetracedDefIdDirectory {
127     ids: Vec<Option<DefId>>
128 }
129
130 impl RetracedDefIdDirectory {
131     pub fn def_id(&self, index: DefPathIndex) -> Option<DefId> {
132         self.ids[index.index as usize]
133     }
134
135     pub fn map(&self, node: &DepNode<DefPathIndex>) -> Option<DepNode<DefId>> {
136         node.map_def(|&index| self.def_id(index))
137     }
138 }
139
140 pub struct DefIdDirectoryBuilder<'a,'tcx:'a> {
141     tcx: TyCtxt<'a, 'tcx, 'tcx>,
142     hash: DefIdMap<DefPathIndex>,
143     directory: DefIdDirectory,
144 }
145
146 impl<'a,'tcx> DefIdDirectoryBuilder<'a,'tcx> {
147     pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> DefIdDirectoryBuilder<'a, 'tcx> {
148         let mut krates: Vec<_> =
149             once(LOCAL_CRATE)
150             .chain(tcx.sess.cstore.crates())
151             .map(|krate| {
152                 CrateInfo {
153                     krate: krate,
154                     name: tcx.crate_name(krate).to_string(),
155                     disambiguator: tcx.crate_disambiguator(krate).to_string()
156                 }
157             })
158             .collect();
159
160         // the result of crates() is not in order, so sort list of
161         // crates so that we can just index it later
162         krates.sort_by_key(|k| k.krate);
163
164         DefIdDirectoryBuilder {
165             tcx: tcx,
166             hash: DefIdMap(),
167             directory: DefIdDirectory::new(krates),
168         }
169     }
170
171     pub fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> {
172         self.tcx
173     }
174
175     pub fn add(&mut self, def_id: DefId) -> DefPathIndex {
176         debug!("DefIdDirectoryBuilder: def_id={:?}", def_id);
177         let tcx = self.tcx;
178         let paths = &mut self.directory.paths;
179         self.hash.entry(def_id)
180                  .or_insert_with(|| {
181                      let def_path = tcx.def_path(def_id);
182                      let index = paths.len() as u32;
183                      paths.push(def_path);
184                      DefPathIndex { index: index }
185                  })
186                  .clone()
187     }
188
189     pub fn map(&mut self, node: &DepNode<DefId>) -> DepNode<DefPathIndex> {
190         node.map_def(|&def_id| Some(self.add(def_id))).unwrap()
191     }
192
193     pub fn directory(&self) -> &DefIdDirectory {
194         &self.directory
195     }
196 }
197
198 impl Debug for DefIdDirectory {
199     fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
200         fmt.debug_list()
201            .entries(self.paths.iter().enumerate())
202            .finish()
203     }
204 }