]> git.lizzy.rs Git - rust.git/blob - src/librustc_incremental/persist/directory.rs
Auto merge of #36609 - brson:relnotes, r=alexcrichton
[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
24 /// Index into the DefIdDirectory
25 #[derive(Copy, Clone, Debug, PartialOrd, Ord, Hash, PartialEq, Eq,
26          RustcEncodable, RustcDecodable)]
27 pub struct DefPathIndex {
28     index: u32
29 }
30
31 #[derive(RustcEncodable, RustcDecodable)]
32 pub struct DefIdDirectory {
33     // N.B. don't use Removable here because these def-ids are loaded
34     // directly without remapping, so loading them should not fail.
35     paths: Vec<DefPath>,
36
37     // For each crate, saves the crate-name/disambiguator so that
38     // later we can match crate-numbers up again.
39     krates: Vec<CrateInfo>,
40 }
41
42 #[derive(Debug, RustcEncodable, RustcDecodable)]
43 pub struct CrateInfo {
44     krate: CrateNum,
45     name: String,
46     disambiguator: String,
47 }
48
49 impl DefIdDirectory {
50     pub fn new(krates: Vec<CrateInfo>) -> DefIdDirectory {
51         DefIdDirectory { paths: vec![], krates: krates }
52     }
53
54     fn max_current_crate(&self, tcx: TyCtxt) -> CrateNum {
55         tcx.sess.cstore.crates()
56                        .into_iter()
57                        .max()
58                        .unwrap_or(LOCAL_CRATE)
59     }
60
61     /// Returns a string form for `index`; useful for debugging
62     pub fn def_path_string(&self, tcx: TyCtxt, index: DefPathIndex) -> String {
63         let path = &self.paths[index.index as usize];
64         if self.krate_still_valid(tcx, self.max_current_crate(tcx), path.krate) {
65             path.to_string(tcx)
66         } else {
67             format!("<crate {} changed>", path.krate)
68         }
69     }
70
71     pub fn krate_still_valid(&self,
72                              tcx: TyCtxt,
73                              max_current_crate: CrateNum,
74                              krate: CrateNum) -> bool {
75         // Check that the crate-number still matches. For now, if it
76         // doesn't, just return None. We could do better, such as
77         // finding the new number.
78
79         if krate > max_current_crate {
80             false
81         } else {
82             let old_info = &self.krates[krate.as_usize()];
83             assert_eq!(old_info.krate, krate);
84             let old_name: &str = &old_info.name;
85             let old_disambiguator: &str = &old_info.disambiguator;
86             let new_name: &str = &tcx.crate_name(krate);
87             let new_disambiguator: &str = &tcx.crate_disambiguator(krate);
88             old_name == new_name && old_disambiguator == new_disambiguator
89         }
90     }
91
92     pub fn retrace(&self, tcx: TyCtxt) -> RetracedDefIdDirectory {
93         let max_current_crate = self.max_current_crate(tcx);
94
95         let ids = self.paths.iter()
96                             .map(|path| {
97                                 if self.krate_still_valid(tcx, max_current_crate, path.krate) {
98                                     tcx.retrace_path(path)
99                                 } else {
100                                     debug!("crate {} changed from {:?} to {:?}/{:?}",
101                                            path.krate,
102                                            self.krates[path.krate.as_usize()],
103                                            tcx.crate_name(path.krate),
104                                            tcx.crate_disambiguator(path.krate));
105                                     None
106                                 }
107                             })
108                             .collect();
109         RetracedDefIdDirectory { ids: ids }
110     }
111 }
112
113 #[derive(Debug, RustcEncodable, RustcDecodable)]
114 pub struct RetracedDefIdDirectory {
115     ids: Vec<Option<DefId>>
116 }
117
118 impl RetracedDefIdDirectory {
119     pub fn def_id(&self, index: DefPathIndex) -> Option<DefId> {
120         self.ids[index.index as usize]
121     }
122
123     pub fn map(&self, node: &DepNode<DefPathIndex>) -> Option<DepNode<DefId>> {
124         node.map_def(|&index| self.def_id(index))
125     }
126 }
127
128 pub struct DefIdDirectoryBuilder<'a,'tcx:'a> {
129     tcx: TyCtxt<'a, 'tcx, 'tcx>,
130     hash: DefIdMap<DefPathIndex>,
131     directory: DefIdDirectory,
132 }
133
134 impl<'a,'tcx> DefIdDirectoryBuilder<'a,'tcx> {
135     pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> DefIdDirectoryBuilder<'a, 'tcx> {
136         let mut krates: Vec<_> =
137             once(LOCAL_CRATE)
138             .chain(tcx.sess.cstore.crates())
139             .map(|krate| {
140                 CrateInfo {
141                     krate: krate,
142                     name: tcx.crate_name(krate).to_string(),
143                     disambiguator: tcx.crate_disambiguator(krate).to_string()
144                 }
145             })
146             .collect();
147
148         // the result of crates() is not in order, so sort list of
149         // crates so that we can just index it later
150         krates.sort_by_key(|k| k.krate);
151
152         DefIdDirectoryBuilder {
153             tcx: tcx,
154             hash: DefIdMap(),
155             directory: DefIdDirectory::new(krates),
156         }
157     }
158
159     pub fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> {
160         self.tcx
161     }
162
163     pub fn add(&mut self, def_id: DefId) -> DefPathIndex {
164         debug!("DefIdDirectoryBuilder: def_id={:?}", def_id);
165         let tcx = self.tcx;
166         let paths = &mut self.directory.paths;
167         self.hash.entry(def_id)
168                  .or_insert_with(|| {
169                      let def_path = tcx.def_path(def_id);
170                      let index = paths.len() as u32;
171                      paths.push(def_path);
172                      DefPathIndex { index: index }
173                  })
174                  .clone()
175     }
176
177     pub fn lookup_def_path(&self, id: DefPathIndex) -> &DefPath {
178         &self.directory.paths[id.index as usize]
179     }
180
181     pub fn map(&mut self, node: &DepNode<DefId>) -> DepNode<DefPathIndex> {
182         node.map_def(|&def_id| Some(self.add(def_id))).unwrap()
183     }
184
185     pub fn directory(&self) -> &DefIdDirectory {
186         &self.directory
187     }
188 }
189
190 impl Debug for DefIdDirectory {
191     fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
192         fmt.debug_list()
193            .entries(self.paths.iter().enumerate())
194            .finish()
195     }
196 }