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};
24 /// Index into the DefIdDirectory
25 #[derive(Copy, Clone, Debug, PartialOrd, Ord, Hash, PartialEq, Eq,
26 RustcEncodable, RustcDecodable)]
27 pub struct DefPathIndex {
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.
37 // For each crate, saves the crate-name/disambiguator so that
38 // later we can match crate-numbers up again.
39 krates: Vec<CrateInfo>,
42 #[derive(Debug, RustcEncodable, RustcDecodable)]
43 pub struct CrateInfo {
46 disambiguator: String,
50 pub fn new(krates: Vec<CrateInfo>) -> DefIdDirectory {
51 DefIdDirectory { paths: vec![], krates: krates }
54 fn max_current_crate(&self, tcx: TyCtxt) -> CrateNum {
55 tcx.sess.cstore.crates()
58 .unwrap_or(LOCAL_CRATE)
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) {
67 format!("<crate {} changed>", path.krate)
71 pub fn krate_still_valid(&self,
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.
79 if krate > max_current_crate {
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
92 pub fn retrace(&self, tcx: TyCtxt) -> RetracedDefIdDirectory {
93 let max_current_crate = self.max_current_crate(tcx);
95 let ids = self.paths.iter()
97 if self.krate_still_valid(tcx, max_current_crate, path.krate) {
98 tcx.retrace_path(path)
100 debug!("crate {} changed from {:?} to {:?}/{:?}",
102 self.krates[path.krate.as_usize()],
103 tcx.crate_name(path.krate),
104 tcx.crate_disambiguator(path.krate));
109 RetracedDefIdDirectory { ids: ids }
113 #[derive(Debug, RustcEncodable, RustcDecodable)]
114 pub struct RetracedDefIdDirectory {
115 ids: Vec<Option<DefId>>
118 impl RetracedDefIdDirectory {
119 pub fn def_id(&self, index: DefPathIndex) -> Option<DefId> {
120 self.ids[index.index as usize]
123 pub fn map(&self, node: &DepNode<DefPathIndex>) -> Option<DepNode<DefId>> {
124 node.map_def(|&index| self.def_id(index))
128 pub struct DefIdDirectoryBuilder<'a,'tcx:'a> {
129 tcx: TyCtxt<'a, 'tcx, 'tcx>,
130 hash: DefIdMap<DefPathIndex>,
131 directory: DefIdDirectory,
134 impl<'a,'tcx> DefIdDirectoryBuilder<'a,'tcx> {
135 pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> DefIdDirectoryBuilder<'a, 'tcx> {
136 let mut krates: Vec<_> =
138 .chain(tcx.sess.cstore.crates())
142 name: tcx.crate_name(krate).to_string(),
143 disambiguator: tcx.crate_disambiguator(krate).to_string()
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);
152 DefIdDirectoryBuilder {
155 directory: DefIdDirectory::new(krates),
159 pub fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> {
163 pub fn add(&mut self, def_id: DefId) -> DefPathIndex {
164 debug!("DefIdDirectoryBuilder: def_id={:?}", def_id);
166 let paths = &mut self.directory.paths;
167 self.hash.entry(def_id)
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 }
177 pub fn lookup_def_path(&self, id: DefPathIndex) -> &DefPath {
178 &self.directory.paths[id.index as usize]
181 pub fn map(&mut self, node: &DepNode<DefId>) -> DepNode<DefPathIndex> {
182 node.map_def(|&def_id| Some(self.add(def_id))).unwrap()
185 pub fn directory(&self) -> &DefIdDirectory {
190 impl Debug for DefIdDirectory {
191 fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
193 .entries(self.paths.iter().enumerate())