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.
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.
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).
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};
23 use std::collections::HashMap;
25 /// Index into the DefIdDirectory
26 #[derive(Copy, Clone, Debug, PartialOrd, Ord, Hash, PartialEq, Eq,
27 RustcEncodable, RustcDecodable)]
28 pub struct DefPathIndex {
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.
38 // For each crate, saves the crate-name/disambiguator so that
39 // later we can match crate-numbers up again.
40 krates: Vec<CrateInfo>,
43 #[derive(Debug, RustcEncodable, RustcDecodable)]
44 pub struct CrateInfo {
47 disambiguator: String,
51 pub fn new(krates: Vec<CrateInfo>) -> DefIdDirectory {
52 DefIdDirectory { paths: vec![], krates: krates }
55 fn max_current_crate(&self, tcx: TyCtxt) -> CrateNum {
56 tcx.sess.cstore.crates()
59 .unwrap_or(LOCAL_CRATE)
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) {
68 format!("<crate {} changed>", path.krate)
72 pub fn krate_still_valid(&self,
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.
80 if krate > max_current_crate {
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
93 pub fn retrace(&self, tcx: TyCtxt) -> RetracedDefIdDirectory {
95 fn make_key(name: &str, disambiguator: &str) -> String {
96 format!("{}/{}", name, disambiguator)
99 let new_krates: HashMap<_, _> =
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))
106 let ids = self.paths.iter()
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)
116 debug!("crate {:?} no longer exists", old_crate_key);
121 RetracedDefIdDirectory { ids: ids }
125 #[derive(Debug, RustcEncodable, RustcDecodable)]
126 pub struct RetracedDefIdDirectory {
127 ids: Vec<Option<DefId>>
130 impl RetracedDefIdDirectory {
131 pub fn def_id(&self, index: DefPathIndex) -> Option<DefId> {
132 self.ids[index.index as usize]
135 pub fn map(&self, node: &DepNode<DefPathIndex>) -> Option<DepNode<DefId>> {
136 node.map_def(|&index| self.def_id(index))
140 pub struct DefIdDirectoryBuilder<'a,'tcx:'a> {
141 tcx: TyCtxt<'a, 'tcx, 'tcx>,
142 hash: DefIdMap<DefPathIndex>,
143 directory: DefIdDirectory,
146 impl<'a,'tcx> DefIdDirectoryBuilder<'a,'tcx> {
147 pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> DefIdDirectoryBuilder<'a, 'tcx> {
148 let mut krates: Vec<_> =
150 .chain(tcx.sess.cstore.crates())
154 name: tcx.crate_name(krate).to_string(),
155 disambiguator: tcx.crate_disambiguator(krate).to_string()
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);
164 DefIdDirectoryBuilder {
167 directory: DefIdDirectory::new(krates),
171 pub fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> {
175 pub fn add(&mut self, def_id: DefId) -> DefPathIndex {
176 debug!("DefIdDirectoryBuilder: def_id={:?}", def_id);
178 let paths = &mut self.directory.paths;
179 self.hash.entry(def_id)
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 }
189 pub fn lookup_def_path(&self, id: DefPathIndex) -> &DefPath {
190 &self.directory.paths[id.index as usize]
193 pub fn map(&mut self, node: &DepNode<DefId>) -> DepNode<DefPathIndex> {
194 node.map_def(|&def_id| Some(self.add(def_id))).unwrap()
197 pub fn directory(&self) -> &DefIdDirectory {
202 impl Debug for DefIdDirectory {
203 fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
205 .entries(self.paths.iter().enumerate())