|
| 1 | +use rustc_data_structures::fingerprint::Fingerprint; |
| 2 | +use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; |
| 3 | +use rustc_data_structures::svh::Svh; |
| 4 | +use rustc_hir::def_id::{CrateNum, LocalDefId, StableCrateId, LOCAL_CRATE}; |
| 5 | +use rustc_hir::intravisit::{self, Visitor}; |
| 6 | +use rustc_hir::{ForeignItem, ImplItem, Item, ItemKind, Mod, TraitItem}; |
| 7 | +use rustc_hir::{ForeignItemId, HirId, ImplItemId, ItemId, ModuleItems, TraitItemId}; |
| 8 | +use rustc_middle::hir::nested_filter; |
| 9 | +use rustc_middle::ty::query::Providers; |
| 10 | +use rustc_middle::ty::TyCtxt; |
| 11 | +use rustc_span::Span; |
| 12 | + |
| 13 | +pub fn provide(providers: &mut Providers) { |
| 14 | + *providers = Providers { crate_hash, hir_module_items, hir_crate_items, ..*providers }; |
| 15 | +} |
| 16 | + |
| 17 | +fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh { |
| 18 | + debug_assert_eq!(crate_num, LOCAL_CRATE); |
| 19 | + let krate = tcx.hir_crate(()); |
| 20 | + let hir_body_hash = krate.hir_hash; |
| 21 | + |
| 22 | + let upstream_crates = upstream_crates(tcx); |
| 23 | + |
| 24 | + // We hash the final, remapped names of all local source files so we |
| 25 | + // don't have to include the path prefix remapping commandline args. |
| 26 | + // If we included the full mapping in the SVH, we could only have |
| 27 | + // reproducible builds by compiling from the same directory. So we just |
| 28 | + // hash the result of the mapping instead of the mapping itself. |
| 29 | + let mut source_file_names: Vec<_> = tcx |
| 30 | + .sess |
| 31 | + .source_map() |
| 32 | + .files() |
| 33 | + .iter() |
| 34 | + .filter(|source_file| source_file.cnum == LOCAL_CRATE) |
| 35 | + .map(|source_file| source_file.name_hash) |
| 36 | + .collect(); |
| 37 | + |
| 38 | + source_file_names.sort_unstable(); |
| 39 | + |
| 40 | + let crate_hash: Fingerprint = tcx.with_stable_hashing_context(|mut hcx| { |
| 41 | + let mut stable_hasher = StableHasher::new(); |
| 42 | + hir_body_hash.hash_stable(&mut hcx, &mut stable_hasher); |
| 43 | + upstream_crates.hash_stable(&mut hcx, &mut stable_hasher); |
| 44 | + source_file_names.hash_stable(&mut hcx, &mut stable_hasher); |
| 45 | + if tcx.sess.opts.debugging_opts.incremental_relative_spans { |
| 46 | + let definitions = tcx.definitions_untracked(); |
| 47 | + let mut owner_spans: Vec<_> = krate |
| 48 | + .owners |
| 49 | + .iter_enumerated() |
| 50 | + .filter_map(|(def_id, info)| { |
| 51 | + let _ = info.as_owner()?; |
| 52 | + let def_path_hash = definitions.def_path_hash(def_id); |
| 53 | + let span = definitions.def_span(def_id); |
| 54 | + debug_assert_eq!(span.parent(), None); |
| 55 | + Some((def_path_hash, span)) |
| 56 | + }) |
| 57 | + .collect(); |
| 58 | + owner_spans.sort_unstable_by_key(|bn| bn.0); |
| 59 | + owner_spans.hash_stable(&mut hcx, &mut stable_hasher); |
| 60 | + } |
| 61 | + tcx.sess.opts.dep_tracking_hash(true).hash_stable(&mut hcx, &mut stable_hasher); |
| 62 | + tcx.sess.local_stable_crate_id().hash_stable(&mut hcx, &mut stable_hasher); |
| 63 | + // Hash visibility information since it does not appear in HIR. |
| 64 | + let resolutions = tcx.resolutions(()); |
| 65 | + resolutions.visibilities.hash_stable(&mut hcx, &mut stable_hasher); |
| 66 | + resolutions.has_pub_restricted.hash_stable(&mut hcx, &mut stable_hasher); |
| 67 | + stable_hasher.finish() |
| 68 | + }); |
| 69 | + |
| 70 | + Svh::new(crate_hash.to_smaller_hash()) |
| 71 | +} |
| 72 | + |
| 73 | +fn upstream_crates(tcx: TyCtxt<'_>) -> Vec<(StableCrateId, Svh)> { |
| 74 | + let mut upstream_crates: Vec<_> = tcx |
| 75 | + .crates(()) |
| 76 | + .iter() |
| 77 | + .map(|&cnum| { |
| 78 | + let stable_crate_id = tcx.stable_crate_id(cnum); |
| 79 | + let hash = tcx.crate_hash(cnum); |
| 80 | + (stable_crate_id, hash) |
| 81 | + }) |
| 82 | + .collect(); |
| 83 | + upstream_crates.sort_unstable_by_key(|&(stable_crate_id, _)| stable_crate_id); |
| 84 | + upstream_crates |
| 85 | +} |
| 86 | + |
| 87 | +fn hir_module_items(tcx: TyCtxt<'_>, module_id: LocalDefId) -> ModuleItems { |
| 88 | + let mut collector = ModuleCollector { |
| 89 | + tcx, |
| 90 | + submodules: Vec::default(), |
| 91 | + items: Vec::default(), |
| 92 | + trait_items: Vec::default(), |
| 93 | + impl_items: Vec::default(), |
| 94 | + foreign_items: Vec::default(), |
| 95 | + }; |
| 96 | + |
| 97 | + let (hir_mod, span, hir_id) = tcx.hir().get_module(module_id); |
| 98 | + collector.visit_mod(hir_mod, span, hir_id); |
| 99 | + |
| 100 | + let ModuleCollector { submodules, items, trait_items, impl_items, foreign_items, .. } = |
| 101 | + collector; |
| 102 | + return ModuleItems { |
| 103 | + submodules: submodules.into_boxed_slice(), |
| 104 | + items: items.into_boxed_slice(), |
| 105 | + trait_items: trait_items.into_boxed_slice(), |
| 106 | + impl_items: impl_items.into_boxed_slice(), |
| 107 | + foreign_items: foreign_items.into_boxed_slice(), |
| 108 | + }; |
| 109 | + |
| 110 | + struct ModuleCollector<'tcx> { |
| 111 | + tcx: TyCtxt<'tcx>, |
| 112 | + submodules: Vec<LocalDefId>, |
| 113 | + items: Vec<ItemId>, |
| 114 | + trait_items: Vec<TraitItemId>, |
| 115 | + impl_items: Vec<ImplItemId>, |
| 116 | + foreign_items: Vec<ForeignItemId>, |
| 117 | + } |
| 118 | + |
| 119 | + impl<'hir> Visitor<'hir> for ModuleCollector<'hir> { |
| 120 | + type NestedFilter = nested_filter::All; |
| 121 | + |
| 122 | + fn nested_visit_map(&mut self) -> Self::Map { |
| 123 | + self.tcx.hir() |
| 124 | + } |
| 125 | + |
| 126 | + fn visit_item(&mut self, item: &'hir Item<'hir>) { |
| 127 | + self.items.push(item.item_id()); |
| 128 | + if let ItemKind::Mod(..) = item.kind { |
| 129 | + // If this declares another module, do not recurse inside it. |
| 130 | + self.submodules.push(item.def_id); |
| 131 | + } else { |
| 132 | + intravisit::walk_item(self, item) |
| 133 | + } |
| 134 | + } |
| 135 | + |
| 136 | + fn visit_trait_item(&mut self, item: &'hir TraitItem<'hir>) { |
| 137 | + self.trait_items.push(item.trait_item_id()); |
| 138 | + intravisit::walk_trait_item(self, item) |
| 139 | + } |
| 140 | + |
| 141 | + fn visit_impl_item(&mut self, item: &'hir ImplItem<'hir>) { |
| 142 | + self.impl_items.push(item.impl_item_id()); |
| 143 | + intravisit::walk_impl_item(self, item) |
| 144 | + } |
| 145 | + |
| 146 | + fn visit_foreign_item(&mut self, item: &'hir ForeignItem<'hir>) { |
| 147 | + self.foreign_items.push(item.foreign_item_id()); |
| 148 | + intravisit::walk_foreign_item(self, item) |
| 149 | + } |
| 150 | + } |
| 151 | +} |
| 152 | + |
| 153 | +fn hir_crate_items(tcx: TyCtxt<'_>, _: ()) -> ModuleItems { |
| 154 | + let mut collector = CrateCollector { |
| 155 | + tcx, |
| 156 | + submodules: Vec::default(), |
| 157 | + items: Vec::default(), |
| 158 | + trait_items: Vec::default(), |
| 159 | + impl_items: Vec::default(), |
| 160 | + foreign_items: Vec::default(), |
| 161 | + }; |
| 162 | + |
| 163 | + tcx.hir().walk_toplevel_module(&mut collector); |
| 164 | + |
| 165 | + let CrateCollector { submodules, items, trait_items, impl_items, foreign_items, .. } = |
| 166 | + collector; |
| 167 | + |
| 168 | + return ModuleItems { |
| 169 | + submodules: submodules.into_boxed_slice(), |
| 170 | + items: items.into_boxed_slice(), |
| 171 | + trait_items: trait_items.into_boxed_slice(), |
| 172 | + impl_items: impl_items.into_boxed_slice(), |
| 173 | + foreign_items: foreign_items.into_boxed_slice(), |
| 174 | + }; |
| 175 | + |
| 176 | + struct CrateCollector<'tcx> { |
| 177 | + tcx: TyCtxt<'tcx>, |
| 178 | + submodules: Vec<LocalDefId>, |
| 179 | + items: Vec<ItemId>, |
| 180 | + trait_items: Vec<TraitItemId>, |
| 181 | + impl_items: Vec<ImplItemId>, |
| 182 | + foreign_items: Vec<ForeignItemId>, |
| 183 | + } |
| 184 | + |
| 185 | + impl<'hir> Visitor<'hir> for CrateCollector<'hir> { |
| 186 | + type NestedFilter = nested_filter::All; |
| 187 | + |
| 188 | + fn nested_visit_map(&mut self) -> Self::Map { |
| 189 | + self.tcx.hir() |
| 190 | + } |
| 191 | + |
| 192 | + fn visit_item(&mut self, item: &'hir Item<'hir>) { |
| 193 | + self.items.push(item.item_id()); |
| 194 | + intravisit::walk_item(self, item) |
| 195 | + } |
| 196 | + |
| 197 | + fn visit_mod(&mut self, m: &'hir Mod<'hir>, _s: Span, n: HirId) { |
| 198 | + self.submodules.push(n.owner); |
| 199 | + intravisit::walk_mod(self, m, n); |
| 200 | + } |
| 201 | + |
| 202 | + fn visit_foreign_item(&mut self, item: &'hir ForeignItem<'hir>) { |
| 203 | + self.foreign_items.push(item.foreign_item_id()); |
| 204 | + intravisit::walk_foreign_item(self, item) |
| 205 | + } |
| 206 | + |
| 207 | + fn visit_trait_item(&mut self, item: &'hir TraitItem<'hir>) { |
| 208 | + self.trait_items.push(item.trait_item_id()); |
| 209 | + intravisit::walk_trait_item(self, item) |
| 210 | + } |
| 211 | + |
| 212 | + fn visit_impl_item(&mut self, item: &'hir ImplItem<'hir>) { |
| 213 | + self.impl_items.push(item.impl_item_id()); |
| 214 | + intravisit::walk_impl_item(self, item) |
| 215 | + } |
| 216 | + } |
| 217 | +} |
0 commit comments