]>
Commit | Line | Data |
---|---|---|
223e47cc LB |
1 | // Decoding metadata from a single crate's metadata |
2 | ||
04454e1e | 3 | use crate::creader::{CStore, CrateMetadataRef}; |
353b0b11 | 4 | use crate::rmeta::table::IsDefault; |
dfeec247 | 5 | use crate::rmeta::*; |
9e0c209e | 6 | |
3dfed10e | 7 | use rustc_ast as ast; |
dfeec247 | 8 | use rustc_data_structures::captures::Captures; |
dfeec247 | 9 | use rustc_data_structures::fx::FxHashMap; |
49aad941 | 10 | use rustc_data_structures::owned_slice::OwnedSlice; |
dfeec247 | 11 | use rustc_data_structures::svh::Svh; |
781aab86 | 12 | use rustc_data_structures::sync::{AppendOnlyVec, AtomicBool, Lock, Lrc, OnceLock}; |
5869c6ff | 13 | use rustc_data_structures::unhash::UnhashMap; |
ba9703b0 | 14 | use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind}; |
923072b8 | 15 | use rustc_expand::proc_macro::{AttrProcMacro, BangProcMacro, DeriveProcMacro}; |
9ffffee4 | 16 | use rustc_hir::def::{CtorKind, DefKind, DocLinkResMap, Res}; |
3dfed10e | 17 | use rustc_hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE}; |
ba9703b0 | 18 | use rustc_hir::definitions::{DefKey, DefPath, DefPathData, DefPathHash}; |
c295e0f8 | 19 | use rustc_hir::diagnostic_items::DiagnosticItems; |
49aad941 | 20 | use rustc_index::{Idx, IndexVec}; |
5099ac24 | 21 | use rustc_middle::metadata::ModChild; |
49aad941 | 22 | use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile; |
04454e1e | 23 | use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo}; |
ba9703b0 | 24 | use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState}; |
ba9703b0 | 25 | use rustc_middle::ty::codec::TyDecoder; |
a2a8927a | 26 | use rustc_middle::ty::fast_reject::SimplifiedType; |
fe692bf9 | 27 | use rustc_middle::ty::{self, ParameterizedOverTcx, Ty, TyCtxt, Visibility}; |
923072b8 FG |
28 | use rustc_serialize::opaque::MemDecoder; |
29 | use rustc_serialize::{Decodable, Decoder}; | |
c295e0f8 XL |
30 | use rustc_session::cstore::{ |
31 | CrateSource, ExternCrate, ForeignModule, LinkagePreference, NativeLib, | |
32 | }; | |
ba9703b0 | 33 | use rustc_session::Session; |
487cf647 | 34 | use rustc_span::hygiene::ExpnIndex; |
487cf647 | 35 | use rustc_span::symbol::{kw, Ident, Symbol}; |
add651ee | 36 | use rustc_span::{self, BytePos, ExpnId, Pos, Span, SpanData, SyntaxContext, DUMMY_SP}; |
9cc50fc6 | 37 | |
ba9703b0 | 38 | use proc_macro::bridge::client::ProcMacro; |
923072b8 | 39 | use std::iter::TrustedLen; |
e74abb32 | 40 | use std::num::NonZeroUsize; |
ba9703b0 | 41 | use std::path::Path; |
fe692bf9 | 42 | use std::sync::atomic::Ordering; |
487cf647 | 43 | use std::{io, iter, mem}; |
223e47cc | 44 | |
a2a8927a | 45 | pub(super) use cstore_impl::provide; |
3dfed10e | 46 | use rustc_span::hygiene::HygieneDecodeContext; |
60c5eb7d XL |
47 | |
48 | mod cstore_impl; | |
49 | ||
c295e0f8 XL |
50 | /// A reference to the raw binary version of crate metadata. |
51 | /// A `MetadataBlob` internally is just a reference counted pointer to | |
52 | /// the actual data, so cloning it is cheap. | |
53 | #[derive(Clone)] | |
49aad941 | 54 | pub(crate) struct MetadataBlob(pub(crate) OwnedSlice); |
c295e0f8 | 55 | |
c295e0f8 XL |
56 | impl std::ops::Deref for MetadataBlob { |
57 | type Target = [u8]; | |
58 | ||
59 | #[inline] | |
60 | fn deref(&self) -> &[u8] { | |
61 | &self.0[..] | |
62 | } | |
63 | } | |
60c5eb7d | 64 | |
487cf647 FG |
65 | /// A map from external crate numbers (as decoded from some crate file) to |
66 | /// local crate numbers (as generated during this session). Each external | |
67 | /// crate may refer to types in other external crates, and each has their | |
68 | /// own crate numbers. | |
923072b8 | 69 | pub(crate) type CrateNumMap = IndexVec<CrateNum, CrateNum>; |
60c5eb7d | 70 | |
923072b8 | 71 | pub(crate) struct CrateMetadata { |
60c5eb7d XL |
72 | /// The primary crate data - binary metadata blob. |
73 | blob: MetadataBlob, | |
74 | ||
75 | // --- Some data pre-decoded from the metadata blob, usually for performance --- | |
fe692bf9 | 76 | /// Data about the top-level items in a crate, as well as various crate-level metadata. |
923072b8 | 77 | root: CrateRoot, |
60c5eb7d XL |
78 | /// Trait impl data. |
79 | /// FIXME: Used only from queries and can use query cache, | |
80 | /// so pre-decoding can probably be avoided. | |
923072b8 | 81 | trait_impls: FxHashMap<(u32, DefIndex), LazyArray<(DefIndex, Option<SimplifiedType>)>>, |
5e7ed085 FG |
82 | /// Inherent impls which do not follow the normal coherence rules. |
83 | /// | |
84 | /// These can be introduced using either `#![rustc_coherence_is_core]` | |
85 | /// or `#[rustc_allow_incoherent_impl]`. | |
923072b8 | 86 | incoherent_impls: FxHashMap<SimplifiedType, LazyArray<DefIndex>>, |
60c5eb7d XL |
87 | /// Proc macro descriptions for this crate, if it's a proc macro crate. |
88 | raw_proc_macros: Option<&'static [ProcMacro]>, | |
89 | /// Source maps for code from the crate. | |
f2b60f7d | 90 | source_map_import_info: Lock<Vec<Option<ImportedSourceFile>>>, |
c295e0f8 XL |
91 | /// For every definition in this crate, maps its `DefPathHash` to its `DefIndex`. |
92 | def_path_hash_map: DefPathHashMapRef<'static>, | |
136023e0 | 93 | /// Likewise for ExpnHash. |
781aab86 | 94 | expn_hash_map: OnceLock<UnhashMap<ExpnHash, ExpnIndex>>, |
60c5eb7d XL |
95 | /// Used for decoding interpret::AllocIds in a cached & thread-safe manner. |
96 | alloc_decoding_state: AllocDecodingState, | |
3dfed10e XL |
97 | /// Caches decoded `DefKey`s. |
98 | def_key_cache: Lock<FxHashMap<DefIndex, DefKey>>, | |
99 | /// Caches decoded `DefPathHash`es. | |
100 | def_path_hash_cache: Lock<FxHashMap<DefIndex, DefPathHash>>, | |
60c5eb7d XL |
101 | |
102 | // --- Other significant crate properties --- | |
60c5eb7d XL |
103 | /// ID of this crate, from the current compilation session's point of view. |
104 | cnum: CrateNum, | |
105 | /// Maps crate IDs as they are were seen from this crate's compilation sessions into | |
106 | /// IDs as they are seen from the current compilation session. | |
107 | cnum_map: CrateNumMap, | |
108 | /// Same ID set as `cnum_map` plus maybe some injected crates like panic runtime. | |
353b0b11 | 109 | dependencies: AppendOnlyVec<CrateNum>, |
60c5eb7d | 110 | /// How to link (or not link) this crate to the currently compiled crate. |
3dfed10e | 111 | dep_kind: Lock<CrateDepKind>, |
60c5eb7d | 112 | /// Filesystem location of this crate. |
5099ac24 | 113 | source: Lrc<CrateSource>, |
fe692bf9 FG |
114 | /// Whether or not this crate should be consider a private dependency. |
115 | /// Used by the 'exported_private_dependencies' lint, and for determining | |
116 | /// whether to emit suggestions that reference this crate. | |
117 | private_dep: AtomicBool, | |
60c5eb7d XL |
118 | /// The hash for the host proc macro. Used to support `-Z dual-proc-macro`. |
119 | host_hash: Option<Svh>, | |
120 | ||
3dfed10e XL |
121 | /// Additional data used for decoding `HygieneData` (e.g. `SyntaxContext` |
122 | /// and `ExpnId`). | |
49aad941 | 123 | /// Note that we store a `HygieneDecodeContext` for each `CrateMetadata`. This is |
3dfed10e XL |
124 | /// because `SyntaxContext` ids are not globally unique, so we need |
125 | /// to track which ids we've decoded on a per-crate basis. | |
126 | hygiene_context: HygieneDecodeContext, | |
127 | ||
60c5eb7d | 128 | // --- Data used only for improving diagnostics --- |
60c5eb7d XL |
129 | /// Information about the `extern crate` item or path that caused this crate to be loaded. |
130 | /// If this is `None`, then the crate was injected (e.g., by the allocator). | |
131 | extern_crate: Lock<Option<ExternCrate>>, | |
132 | } | |
133 | ||
dfeec247 | 134 | /// Holds information about a rustc_span::SourceFile imported from another crate. |
f2b60f7d FG |
135 | /// See `imported_source_file()` for more information. |
136 | #[derive(Clone)] | |
60c5eb7d XL |
137 | struct ImportedSourceFile { |
138 | /// This SourceFile's byte-offset within the source_map of its original crate | |
dfeec247 | 139 | original_start_pos: rustc_span::BytePos, |
60c5eb7d | 140 | /// The end of this SourceFile within the source_map of its original crate |
dfeec247 | 141 | original_end_pos: rustc_span::BytePos, |
60c5eb7d | 142 | /// The imported SourceFile's representation within the local source_map |
dfeec247 | 143 | translated_source_file: Lrc<rustc_span::SourceFile>, |
60c5eb7d XL |
144 | } |
145 | ||
146 | pub(super) struct DecodeContext<'a, 'tcx> { | |
923072b8 | 147 | opaque: MemDecoder<'a>, |
74b04a01 | 148 | cdata: Option<CrateMetadataRef<'a>>, |
c295e0f8 | 149 | blob: &'a MetadataBlob, |
dc9dc135 XL |
150 | sess: Option<&'tcx Session>, |
151 | tcx: Option<TyCtxt<'tcx>>, | |
c34b1796 | 152 | |
c30ab7b3 | 153 | lazy_state: LazyState, |
0531ce1d | 154 | |
94b46f34 XL |
155 | // Used for decoding interpret::AllocIds in a cached & thread-safe manner. |
156 | alloc_decoding_session: Option<AllocDecodingSession<'a>>, | |
223e47cc LB |
157 | } |
158 | ||
9e0c209e | 159 | /// Abstract over the various ways one can create metadata decoders. |
60c5eb7d | 160 | pub(super) trait Metadata<'a, 'tcx>: Copy { |
c295e0f8 XL |
161 | fn blob(self) -> &'a MetadataBlob; |
162 | ||
74b04a01 | 163 | fn cdata(self) -> Option<CrateMetadataRef<'a>> { |
dfeec247 XL |
164 | None |
165 | } | |
166 | fn sess(self) -> Option<&'tcx Session> { | |
167 | None | |
168 | } | |
169 | fn tcx(self) -> Option<TyCtxt<'tcx>> { | |
170 | None | |
171 | } | |
b039eaaf | 172 | |
9e0c209e | 173 | fn decoder(self, pos: usize) -> DecodeContext<'a, 'tcx> { |
476ff2be | 174 | let tcx = self.tcx(); |
9e0c209e | 175 | DecodeContext { |
923072b8 | 176 | opaque: MemDecoder::new(self.blob(), pos), |
9e0c209e | 177 | cdata: self.cdata(), |
c295e0f8 | 178 | blob: self.blob(), |
476ff2be | 179 | sess: self.sess().or(tcx.map(|tcx| tcx.sess)), |
3b2f2976 | 180 | tcx, |
c30ab7b3 | 181 | lazy_state: LazyState::NoNode, |
dfeec247 XL |
182 | alloc_decoding_session: self |
183 | .cdata() | |
74b04a01 | 184 | .map(|cdata| cdata.cdata.alloc_decoding_state.new_decoding_session()), |
9e0c209e SL |
185 | } |
186 | } | |
b039eaaf SL |
187 | } |
188 | ||
9e0c209e | 189 | impl<'a, 'tcx> Metadata<'a, 'tcx> for &'a MetadataBlob { |
c295e0f8 XL |
190 | #[inline] |
191 | fn blob(self) -> &'a MetadataBlob { | |
192 | self | |
9e0c209e | 193 | } |
223e47cc LB |
194 | } |
195 | ||
dc9dc135 | 196 | impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a MetadataBlob, &'tcx Session) { |
c295e0f8 XL |
197 | #[inline] |
198 | fn blob(self) -> &'a MetadataBlob { | |
199 | self.0 | |
abe05a73 XL |
200 | } |
201 | ||
c295e0f8 | 202 | #[inline] |
dc9dc135 | 203 | fn sess(self) -> Option<&'tcx Session> { |
abe05a73 XL |
204 | let (_, sess) = self; |
205 | Some(sess) | |
206 | } | |
207 | } | |
208 | ||
5099ac24 | 209 | impl<'a, 'tcx> Metadata<'a, 'tcx> for CrateMetadataRef<'a> { |
c295e0f8 XL |
210 | #[inline] |
211 | fn blob(self) -> &'a MetadataBlob { | |
5099ac24 | 212 | &self.cdata.blob |
c30ab7b3 | 213 | } |
c295e0f8 | 214 | #[inline] |
74b04a01 | 215 | fn cdata(self) -> Option<CrateMetadataRef<'a>> { |
5099ac24 | 216 | Some(self) |
c30ab7b3 | 217 | } |
a7813a04 XL |
218 | } |
219 | ||
5099ac24 | 220 | impl<'a, 'tcx> Metadata<'a, 'tcx> for (CrateMetadataRef<'a>, &'tcx Session) { |
c295e0f8 XL |
221 | #[inline] |
222 | fn blob(self) -> &'a MetadataBlob { | |
5099ac24 | 223 | &self.0.cdata.blob |
476ff2be | 224 | } |
c295e0f8 | 225 | #[inline] |
74b04a01 | 226 | fn cdata(self) -> Option<CrateMetadataRef<'a>> { |
5099ac24 | 227 | Some(self.0) |
476ff2be | 228 | } |
c295e0f8 | 229 | #[inline] |
dc9dc135 | 230 | fn sess(self) -> Option<&'tcx Session> { |
5099ac24 | 231 | Some(self.1) |
476ff2be SL |
232 | } |
233 | } | |
234 | ||
5099ac24 | 235 | impl<'a, 'tcx> Metadata<'a, 'tcx> for (CrateMetadataRef<'a>, TyCtxt<'tcx>) { |
c295e0f8 XL |
236 | #[inline] |
237 | fn blob(self) -> &'a MetadataBlob { | |
5099ac24 | 238 | &self.0.cdata.blob |
c30ab7b3 | 239 | } |
c295e0f8 | 240 | #[inline] |
74b04a01 | 241 | fn cdata(self) -> Option<CrateMetadataRef<'a>> { |
5099ac24 | 242 | Some(self.0) |
c30ab7b3 | 243 | } |
c295e0f8 | 244 | #[inline] |
dc9dc135 | 245 | fn tcx(self) -> Option<TyCtxt<'tcx>> { |
c30ab7b3 SL |
246 | Some(self.1) |
247 | } | |
223e47cc LB |
248 | } |
249 | ||
923072b8 | 250 | impl<T: ParameterizedOverTcx> LazyValue<T> { |
781aab86 | 251 | #[inline] |
923072b8 FG |
252 | fn decode<'a, 'tcx, M: Metadata<'a, 'tcx>>(self, metadata: M) -> T::Value<'tcx> |
253 | where | |
254 | T::Value<'tcx>: Decodable<DecodeContext<'a, 'tcx>>, | |
255 | { | |
e74abb32 | 256 | let mut dcx = metadata.decoder(self.position.get()); |
9e0c209e | 257 | dcx.lazy_state = LazyState::NodeStart(self.position); |
923072b8 | 258 | T::Value::decode(&mut dcx) |
62682a34 SL |
259 | } |
260 | } | |
261 | ||
923072b8 FG |
262 | struct DecodeIterator<'a, 'tcx, T> { |
263 | elem_counter: std::ops::Range<usize>, | |
264 | dcx: DecodeContext<'a, 'tcx>, | |
265 | _phantom: PhantomData<fn() -> T>, | |
04454e1e FG |
266 | } |
267 | ||
923072b8 FG |
268 | impl<'a, 'tcx, T: Decodable<DecodeContext<'a, 'tcx>>> Iterator for DecodeIterator<'a, 'tcx, T> { |
269 | type Item = T; | |
5e7ed085 | 270 | |
923072b8 FG |
271 | #[inline(always)] |
272 | fn next(&mut self) -> Option<Self::Item> { | |
273 | self.elem_counter.next().map(|_| T::decode(&mut self.dcx)) | |
5e7ed085 | 274 | } |
5e7ed085 | 275 | |
923072b8 FG |
276 | #[inline(always)] |
277 | fn size_hint(&self) -> (usize, Option<usize>) { | |
278 | self.elem_counter.size_hint() | |
5e7ed085 FG |
279 | } |
280 | } | |
281 | ||
923072b8 FG |
282 | impl<'a, 'tcx, T: Decodable<DecodeContext<'a, 'tcx>>> ExactSizeIterator |
283 | for DecodeIterator<'a, 'tcx, T> | |
5e7ed085 | 284 | { |
923072b8 FG |
285 | fn len(&self) -> usize { |
286 | self.elem_counter.len() | |
5e7ed085 FG |
287 | } |
288 | } | |
289 | ||
923072b8 FG |
290 | unsafe impl<'a, 'tcx, T: Decodable<DecodeContext<'a, 'tcx>>> TrustedLen |
291 | for DecodeIterator<'a, 'tcx, T> | |
5e7ed085 | 292 | { |
5e7ed085 FG |
293 | } |
294 | ||
923072b8 | 295 | impl<T: ParameterizedOverTcx> LazyArray<T> { |
781aab86 | 296 | #[inline] |
923072b8 | 297 | fn decode<'a, 'tcx, M: Metadata<'a, 'tcx>>( |
5e7ed085 | 298 | self, |
923072b8 FG |
299 | metadata: M, |
300 | ) -> DecodeIterator<'a, 'tcx, T::Value<'tcx>> | |
301 | where | |
302 | T::Value<'tcx>: Decodable<DecodeContext<'a, 'tcx>>, | |
303 | { | |
304 | let mut dcx = metadata.decoder(self.position.get()); | |
305 | dcx.lazy_state = LazyState::NodeStart(self.position); | |
306 | DecodeIterator { elem_counter: (0..self.num_elems), dcx, _phantom: PhantomData } | |
04454e1e FG |
307 | } |
308 | } | |
309 | ||
9e0c209e | 310 | impl<'a, 'tcx> DecodeContext<'a, 'tcx> { |
c295e0f8 | 311 | #[inline] |
e74abb32 | 312 | fn tcx(&self) -> TyCtxt<'tcx> { |
353b0b11 | 313 | let Some(tcx) = self.tcx else { |
add651ee FG |
314 | bug!( |
315 | "No TyCtxt found for decoding. \ | |
316 | You need to explicitly pass `(crate_metadata_ref, tcx)` to `decode` instead of just `crate_metadata_ref`." | |
317 | ); | |
353b0b11 FG |
318 | }; |
319 | tcx | |
c295e0f8 XL |
320 | } |
321 | ||
322 | #[inline] | |
323 | pub fn blob(&self) -> &'a MetadataBlob { | |
324 | self.blob | |
9e0c209e | 325 | } |
223e47cc | 326 | |
c295e0f8 XL |
327 | #[inline] |
328 | pub fn cdata(&self) -> CrateMetadataRef<'a> { | |
329 | debug_assert!(self.cdata.is_some(), "missing CrateMetadata in DecodeContext"); | |
330 | self.cdata.unwrap() | |
9e0c209e | 331 | } |
a7813a04 | 332 | |
04454e1e | 333 | #[inline] |
17df50a5 | 334 | fn map_encoded_cnum_to_current(&self, cnum: CrateNum) -> CrateNum { |
04454e1e | 335 | self.cdata().map_encoded_cnum_to_current(cnum) |
17df50a5 XL |
336 | } |
337 | ||
923072b8 FG |
338 | #[inline] |
339 | fn read_lazy_offset_then<T>(&mut self, f: impl Fn(NonZeroUsize) -> T) -> T { | |
5099ac24 | 340 | let distance = self.read_usize(); |
9e0c209e | 341 | let position = match self.lazy_state { |
e1599b0c | 342 | LazyState::NoNode => bug!("read_lazy_with_meta: outside of a metadata node"), |
9e0c209e | 343 | LazyState::NodeStart(start) => { |
e74abb32 | 344 | let start = start.get(); |
5099ac24 FG |
345 | assert!(distance <= start); |
346 | start - distance | |
9e0c209e | 347 | } |
5099ac24 | 348 | LazyState::Previous(last_pos) => last_pos.get() + distance, |
9e0c209e | 349 | }; |
923072b8 FG |
350 | let position = NonZeroUsize::new(position).unwrap(); |
351 | self.lazy_state = LazyState::Previous(position); | |
352 | f(position) | |
353 | } | |
354 | ||
355 | fn read_lazy<T>(&mut self) -> LazyValue<T> { | |
356 | self.read_lazy_offset_then(|pos| LazyValue::from_position(pos)) | |
357 | } | |
358 | ||
359 | fn read_lazy_array<T>(&mut self, len: usize) -> LazyArray<T> { | |
360 | self.read_lazy_offset_then(|pos| LazyArray::from_position_and_num_elems(pos, len)) | |
361 | } | |
362 | ||
781aab86 FG |
363 | fn read_lazy_table<I, T>(&mut self, width: usize, len: usize) -> LazyTable<I, T> { |
364 | self.read_lazy_offset_then(|pos| LazyTable::from_position_and_encoded_size(pos, width, len)) | |
9e0c209e | 365 | } |
c295e0f8 XL |
366 | |
367 | #[inline] | |
5e7ed085 | 368 | pub fn read_raw_bytes(&mut self, len: usize) -> &[u8] { |
c295e0f8 XL |
369 | self.opaque.read_raw_bytes(len) |
370 | } | |
223e47cc LB |
371 | } |
372 | ||
923072b8 | 373 | impl<'a, 'tcx> TyDecoder for DecodeContext<'a, 'tcx> { |
3dfed10e XL |
374 | const CLEAR_CROSS_CRATE: bool = true; |
375 | ||
923072b8 FG |
376 | type I = TyCtxt<'tcx>; |
377 | ||
abe05a73 | 378 | #[inline] |
923072b8 FG |
379 | fn interner(&self) -> Self::I { |
380 | self.tcx() | |
abe05a73 XL |
381 | } |
382 | ||
5099ac24 | 383 | fn cached_ty_for_shorthand<F>(&mut self, shorthand: usize, or_insert_with: F) -> Ty<'tcx> |
dfeec247 | 384 | where |
5099ac24 | 385 | F: FnOnce(&mut Self) -> Ty<'tcx>, |
abe05a73 XL |
386 | { |
387 | let tcx = self.tcx(); | |
223e47cc | 388 | |
17df50a5 | 389 | let key = ty::CReaderCacheKey { cnum: Some(self.cdata().cnum), pos: shorthand }; |
1a4d82fc | 390 | |
f035d41b | 391 | if let Some(&ty) = tcx.ty_rcache.borrow().get(&key) { |
5099ac24 | 392 | return ty; |
abe05a73 | 393 | } |
223e47cc | 394 | |
5099ac24 | 395 | let ty = or_insert_with(self); |
f035d41b | 396 | tcx.ty_rcache.borrow_mut().insert(key, ty); |
5099ac24 | 397 | ty |
9e0c209e | 398 | } |
62682a34 | 399 | |
abe05a73 | 400 | fn with_position<F, R>(&mut self, pos: usize, f: F) -> R |
dfeec247 XL |
401 | where |
402 | F: FnOnce(&mut Self) -> R, | |
abe05a73 | 403 | { |
49aad941 | 404 | let new_opaque = MemDecoder::new(self.opaque.data(), pos); |
abe05a73 XL |
405 | let old_opaque = mem::replace(&mut self.opaque, new_opaque); |
406 | let old_state = mem::replace(&mut self.lazy_state, LazyState::NoNode); | |
407 | let r = f(self); | |
408 | self.opaque = old_opaque; | |
409 | self.lazy_state = old_state; | |
410 | r | |
411 | } | |
412 | ||
5099ac24 | 413 | fn decode_alloc_id(&mut self) -> rustc_middle::mir::interpret::AllocId { |
3dfed10e XL |
414 | if let Some(alloc_decoding_session) = self.alloc_decoding_session { |
415 | alloc_decoding_session.decode_alloc_id(self) | |
416 | } else { | |
417 | bug!("Attempting to decode interpret::AllocId without CrateMetadata") | |
418 | } | |
9e0c209e | 419 | } |
223e47cc LB |
420 | } |
421 | ||
3dfed10e | 422 | impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for CrateNum { |
781aab86 | 423 | #[inline] |
5099ac24 FG |
424 | fn decode(d: &mut DecodeContext<'a, 'tcx>) -> CrateNum { |
425 | let cnum = CrateNum::from_u32(d.read_u32()); | |
426 | d.map_encoded_cnum_to_current(cnum) | |
9e0c209e | 427 | } |
970d7e83 LB |
428 | } |
429 | ||
3dfed10e | 430 | impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for DefIndex { |
781aab86 | 431 | #[inline] |
5099ac24 FG |
432 | fn decode(d: &mut DecodeContext<'a, 'tcx>) -> DefIndex { |
433 | DefIndex::from_u32(d.read_u32()) | |
e74abb32 XL |
434 | } |
435 | } | |
abe05a73 | 436 | |
136023e0 | 437 | impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for ExpnIndex { |
781aab86 | 438 | #[inline] |
5099ac24 FG |
439 | fn decode(d: &mut DecodeContext<'a, 'tcx>) -> ExpnIndex { |
440 | ExpnIndex::from_u32(d.read_u32()) | |
136023e0 XL |
441 | } |
442 | } | |
443 | ||
f2b60f7d | 444 | impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for ast::AttrId { |
781aab86 | 445 | #[inline] |
f2b60f7d FG |
446 | fn decode(d: &mut DecodeContext<'a, 'tcx>) -> ast::AttrId { |
447 | let sess = d.sess.expect("can't decode AttrId without Session"); | |
448 | sess.parse_sess.attr_id_generator.mk_attr_id() | |
449 | } | |
450 | } | |
451 | ||
3dfed10e | 452 | impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for SyntaxContext { |
5099ac24 | 453 | fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> SyntaxContext { |
3dfed10e | 454 | let cdata = decoder.cdata(); |
353b0b11 FG |
455 | |
456 | let Some(sess) = decoder.sess else { | |
add651ee FG |
457 | bug!( |
458 | "Cannot decode SyntaxContext without Session.\ | |
459 | You need to explicitly pass `(crate_metadata_ref, tcx)` to `decode` instead of just `crate_metadata_ref`." | |
460 | ); | |
353b0b11 FG |
461 | }; |
462 | ||
fe692bf9 | 463 | let cname = cdata.root.name(); |
3dfed10e XL |
464 | rustc_span::hygiene::decode_syntax_context(decoder, &cdata.hygiene_context, |_, id| { |
465 | debug!("SpecializedDecoder<SyntaxContext>: decoding {}", id); | |
5099ac24 | 466 | cdata |
3dfed10e XL |
467 | .root |
468 | .syntax_contexts | |
5099ac24 | 469 | .get(cdata, id) |
9c376795 | 470 | .unwrap_or_else(|| panic!("Missing SyntaxContext {id:?} for crate {cname:?}")) |
5099ac24 | 471 | .decode((cdata, sess)) |
3dfed10e | 472 | }) |
1a4d82fc JJ |
473 | } |
474 | } | |
475 | ||
3dfed10e | 476 | impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for ExpnId { |
5099ac24 | 477 | fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> ExpnId { |
3dfed10e | 478 | let local_cdata = decoder.cdata(); |
353b0b11 FG |
479 | |
480 | let Some(sess) = decoder.sess else { | |
add651ee FG |
481 | bug!( |
482 | "Cannot decode ExpnId without Session. \ | |
483 | You need to explicitly pass `(crate_metadata_ref, tcx)` to `decode` instead of just `crate_metadata_ref`." | |
484 | ); | |
353b0b11 | 485 | }; |
0531ce1d | 486 | |
5099ac24 FG |
487 | let cnum = CrateNum::decode(decoder); |
488 | let index = u32::decode(decoder); | |
136023e0 XL |
489 | |
490 | let expn_id = rustc_span::hygiene::decode_expn_id(cnum, index, |expn_id| { | |
491 | let ExpnId { krate: cnum, local_id: index } = expn_id; | |
492 | // Lookup local `ExpnData`s in our own crate data. Foreign `ExpnData`s | |
493 | // are stored in the owning crate, to avoid duplication. | |
494 | debug_assert_ne!(cnum, LOCAL_CRATE); | |
495 | let crate_data = if cnum == local_cdata.cnum { | |
496 | local_cdata | |
497 | } else { | |
498 | local_cdata.cstore.get_crate_data(cnum) | |
499 | }; | |
500 | let expn_data = crate_data | |
501 | .root | |
502 | .expn_data | |
5099ac24 | 503 | .get(crate_data, index) |
136023e0 | 504 | .unwrap() |
5099ac24 | 505 | .decode((crate_data, sess)); |
136023e0 XL |
506 | let expn_hash = crate_data |
507 | .root | |
508 | .expn_hashes | |
5099ac24 | 509 | .get(crate_data, index) |
136023e0 | 510 | .unwrap() |
5099ac24 | 511 | .decode((crate_data, sess)); |
136023e0 XL |
512 | (expn_data, expn_hash) |
513 | }); | |
5099ac24 | 514 | expn_id |
0531ce1d XL |
515 | } |
516 | } | |
517 | ||
3dfed10e | 518 | impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for Span { |
5099ac24 | 519 | fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Span { |
add651ee FG |
520 | let mode = SpanEncodingMode::decode(decoder); |
521 | let data = match mode { | |
522 | SpanEncodingMode::Direct => SpanData::decode(decoder), | |
523 | SpanEncodingMode::Shorthand(position) => decoder.with_position(position, |decoder| { | |
524 | let mode = SpanEncodingMode::decode(decoder); | |
525 | debug_assert!(matches!(mode, SpanEncodingMode::Direct)); | |
526 | SpanData::decode(decoder) | |
527 | }), | |
528 | }; | |
529 | Span::new(data.lo, data.hi, data.ctxt, data.parent) | |
530 | } | |
531 | } | |
532 | ||
533 | impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for SpanData { | |
534 | fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> SpanData { | |
5099ac24 FG |
535 | let ctxt = SyntaxContext::decode(decoder); |
536 | let tag = u8::decode(decoder); | |
85aaf69f | 537 | |
cdc7bbd5 | 538 | if tag == TAG_PARTIAL_SPAN { |
add651ee | 539 | return DUMMY_SP.with_ctxt(ctxt).data(); |
ff7c6d11 XL |
540 | } |
541 | ||
ba9703b0 | 542 | debug_assert!(tag == TAG_VALID_SPAN_LOCAL || tag == TAG_VALID_SPAN_FOREIGN); |
2c00a5a8 | 543 | |
5099ac24 FG |
544 | let lo = BytePos::decode(decoder); |
545 | let len = BytePos::decode(decoder); | |
2c00a5a8 | 546 | let hi = lo + len; |
ff7c6d11 | 547 | |
3c0e092e | 548 | let Some(sess) = decoder.sess else { |
add651ee FG |
549 | bug!( |
550 | "Cannot decode Span without Session. \ | |
551 | You need to explicitly pass `(crate_metadata_ref, tcx)` to `decode` instead of just `crate_metadata_ref`." | |
552 | ) | |
9e0c209e | 553 | }; |
85aaf69f | 554 | |
f2b60f7d FG |
555 | // Index of the file in the corresponding crate's list of encoded files. |
556 | let metadata_index = u32::decode(decoder); | |
557 | ||
ba9703b0 XL |
558 | // There are two possibilities here: |
559 | // 1. This is a 'local span', which is located inside a `SourceFile` | |
560 | // that came from this crate. In this case, we use the source map data | |
561 | // encoded in this crate. This branch should be taken nearly all of the time. | |
562 | // 2. This is a 'foreign span', which is located inside a `SourceFile` | |
563 | // that came from a *different* crate (some crate upstream of the one | |
564 | // whose metadata we're looking at). For example, consider this dependency graph: | |
565 | // | |
566 | // A -> B -> C | |
567 | // | |
568 | // Suppose that we're currently compiling crate A, and start deserializing | |
569 | // metadata from crate B. When we deserialize a Span from crate B's metadata, | |
5e7ed085 | 570 | // there are two possibilities: |
ba9703b0 XL |
571 | // |
572 | // 1. The span references a file from crate B. This makes it a 'local' span, | |
573 | // which means that we can use crate B's serialized source map information. | |
574 | // 2. The span references a file from crate C. This makes it a 'foreign' span, | |
575 | // which means we need to use Crate *C* (not crate B) to determine the source | |
576 | // map information. We only record source map information for a file in the | |
577 | // crate that 'owns' it, so deserializing a Span may require us to look at | |
578 | // a transitive dependency. | |
579 | // | |
580 | // When we encode a foreign span, we adjust its 'lo' and 'high' values | |
581 | // to be based on the *foreign* crate (e.g. crate C), not the crate | |
582 | // we are writing metadata for (e.g. crate B). This allows us to | |
583 | // treat the 'local' and 'foreign' cases almost identically during deserialization: | |
f2b60f7d | 584 | // we can call `imported_source_file` for the proper crate, and binary search |
ba9703b0 | 585 | // through the returned slice using our span. |
f2b60f7d FG |
586 | let source_file = if tag == TAG_VALID_SPAN_LOCAL { |
587 | decoder.cdata().imported_source_file(metadata_index, sess) | |
ba9703b0 | 588 | } else { |
f035d41b XL |
589 | // When we encode a proc-macro crate, all `Span`s should be encoded |
590 | // with `TAG_VALID_SPAN_LOCAL` | |
3dfed10e | 591 | if decoder.cdata().root.is_proc_macro_crate() { |
ba9703b0 XL |
592 | // Decode `CrateNum` as u32 - using `CrateNum::decode` will ICE |
593 | // since we don't have `cnum_map` populated. | |
5099ac24 | 594 | let cnum = u32::decode(decoder); |
f035d41b XL |
595 | panic!( |
596 | "Decoding of crate {:?} tried to access proc-macro dep {:?}", | |
fe692bf9 | 597 | decoder.cdata().root.header.name, |
f035d41b XL |
598 | cnum |
599 | ); | |
ba9703b0 XL |
600 | } |
601 | // tag is TAG_VALID_SPAN_FOREIGN, checked by `debug_assert` above | |
5099ac24 | 602 | let cnum = CrateNum::decode(decoder); |
ba9703b0 XL |
603 | debug!( |
604 | "SpecializedDecoder<Span>::specialized_decode: loading source files from cnum {:?}", | |
605 | cnum | |
606 | ); | |
607 | ||
3dfed10e | 608 | let foreign_data = decoder.cdata().cstore.get_crate_data(cnum); |
f2b60f7d | 609 | foreign_data.imported_source_file(metadata_index, sess) |
9e0c209e SL |
610 | }; |
611 | ||
f2b60f7d | 612 | // Make sure our span is well-formed. |
ba9703b0 | 613 | debug_assert!( |
f2b60f7d FG |
614 | lo + source_file.original_start_pos <= source_file.original_end_pos, |
615 | "Malformed encoded span: lo={:?} source_file.original_start_pos={:?} source_file.original_end_pos={:?}", | |
ba9703b0 XL |
616 | lo, |
617 | source_file.original_start_pos, | |
618 | source_file.original_end_pos | |
619 | ); | |
ff7c6d11 | 620 | |
f2b60f7d | 621 | // Make sure we correctly filtered out invalid spans during encoding. |
ba9703b0 | 622 | debug_assert!( |
f2b60f7d FG |
623 | hi + source_file.original_start_pos <= source_file.original_end_pos, |
624 | "Malformed encoded span: hi={:?} source_file.original_start_pos={:?} source_file.original_end_pos={:?}", | |
ba9703b0 XL |
625 | hi, |
626 | source_file.original_start_pos, | |
627 | source_file.original_end_pos | |
628 | ); | |
ff7c6d11 | 629 | |
f2b60f7d FG |
630 | let lo = lo + source_file.translated_source_file.start_pos; |
631 | let hi = hi + source_file.translated_source_file.start_pos; | |
9e0c209e | 632 | |
c295e0f8 | 633 | // Do not try to decode parent for foreign spans. |
add651ee | 634 | SpanData { lo, hi, ctxt, parent: None } |
e1599b0c XL |
635 | } |
636 | } | |
637 | ||
f2b60f7d FG |
638 | impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for Symbol { |
639 | fn decode(d: &mut DecodeContext<'a, 'tcx>) -> Self { | |
640 | let tag = d.read_u8(); | |
641 | ||
642 | match tag { | |
643 | SYMBOL_STR => { | |
644 | let s = d.read_str(); | |
645 | Symbol::intern(s) | |
646 | } | |
647 | SYMBOL_OFFSET => { | |
648 | // read str offset | |
649 | let pos = d.read_usize(); | |
f2b60f7d | 650 | |
49aad941 FG |
651 | // move to str offset and read |
652 | d.opaque.with_position(pos, |d| { | |
653 | let s = d.read_str(); | |
654 | Symbol::intern(s) | |
655 | }) | |
f2b60f7d FG |
656 | } |
657 | SYMBOL_PREINTERNED => { | |
658 | let symbol_index = d.read_u32(); | |
659 | Symbol::new_from_decoded(symbol_index) | |
660 | } | |
661 | _ => unreachable!(), | |
662 | } | |
663 | } | |
664 | } | |
665 | ||
fe692bf9 | 666 | impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for &'tcx [(ty::Clause<'tcx>, Span)] { |
5099ac24 | 667 | fn decode(d: &mut DecodeContext<'a, 'tcx>) -> Self { |
3dfed10e XL |
668 | ty::codec::RefDecodable::decode(d) |
669 | } | |
670 | } | |
671 | ||
923072b8 | 672 | impl<'a, 'tcx, T> Decodable<DecodeContext<'a, 'tcx>> for LazyValue<T> { |
5099ac24 | 673 | fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Self { |
923072b8 | 674 | decoder.read_lazy() |
2c00a5a8 XL |
675 | } |
676 | } | |
677 | ||
923072b8 | 678 | impl<'a, 'tcx, T> Decodable<DecodeContext<'a, 'tcx>> for LazyArray<T> { |
781aab86 | 679 | #[inline] |
5099ac24 FG |
680 | fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Self { |
681 | let len = decoder.read_usize(); | |
9ffffee4 | 682 | if len == 0 { LazyArray::default() } else { decoder.read_lazy_array(len) } |
3dfed10e XL |
683 | } |
684 | } | |
685 | ||
923072b8 | 686 | impl<'a, 'tcx, I: Idx, T> Decodable<DecodeContext<'a, 'tcx>> for LazyTable<I, T> { |
5099ac24 | 687 | fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Self { |
781aab86 | 688 | let width = decoder.read_usize(); |
5099ac24 | 689 | let len = decoder.read_usize(); |
781aab86 | 690 | decoder.read_lazy_table(width, len) |
ff7c6d11 XL |
691 | } |
692 | } | |
693 | ||
dfeec247 | 694 | implement_ty_decoder!(DecodeContext<'a, 'tcx>); |
ea8adc8c | 695 | |
923072b8 | 696 | impl MetadataBlob { |
923072b8 | 697 | pub(crate) fn is_compatible(&self) -> bool { |
c295e0f8 | 698 | self.blob().starts_with(METADATA_HEADER) |
85aaf69f | 699 | } |
85aaf69f | 700 | |
923072b8 FG |
701 | pub(crate) fn get_rustc_version(&self) -> String { |
702 | LazyValue::<String>::from_position(NonZeroUsize::new(METADATA_HEADER.len() + 4).unwrap()) | |
dfeec247 | 703 | .decode(self) |
476ff2be SL |
704 | } |
705 | ||
fe692bf9 FG |
706 | pub(crate) fn get_header(&self) -> CrateHeader { |
707 | let slice = &self.blob()[..]; | |
708 | let offset = METADATA_HEADER.len(); | |
709 | ||
710 | let pos_bytes = slice[offset..][..4].try_into().unwrap(); | |
711 | let pos = u32::from_be_bytes(pos_bytes) as usize; | |
712 | ||
713 | LazyValue::<CrateHeader>::from_position(NonZeroUsize::new(pos).unwrap()).decode(self) | |
714 | } | |
715 | ||
923072b8 | 716 | pub(crate) fn get_root(&self) -> CrateRoot { |
c295e0f8 | 717 | let slice = &self.blob()[..]; |
9e0c209e | 718 | let offset = METADATA_HEADER.len(); |
9c376795 FG |
719 | |
720 | let pos_bytes = slice[offset..][..4].try_into().unwrap(); | |
721 | let pos = u32::from_be_bytes(pos_bytes) as usize; | |
722 | ||
923072b8 | 723 | LazyValue::<CrateRoot>::from_position(NonZeroUsize::new(pos).unwrap()).decode(self) |
9e0c209e SL |
724 | } |
725 | ||
781aab86 FG |
726 | pub(crate) fn list_crate_metadata( |
727 | &self, | |
728 | out: &mut dyn io::Write, | |
729 | ls_kinds: &[String], | |
730 | ) -> io::Result<()> { | |
9e0c209e | 731 | let root = self.get_root(); |
781aab86 FG |
732 | |
733 | let all_ls_kinds = vec![ | |
734 | "root".to_owned(), | |
735 | "lang_items".to_owned(), | |
736 | "features".to_owned(), | |
737 | "items".to_owned(), | |
738 | ]; | |
739 | let ls_kinds = if ls_kinds.contains(&"all".to_owned()) { &all_ls_kinds } else { ls_kinds }; | |
740 | ||
741 | for kind in ls_kinds { | |
742 | match &**kind { | |
743 | "root" => { | |
744 | writeln!(out, "Crate info:")?; | |
745 | writeln!(out, "name {}{}", root.name(), root.extra_filename)?; | |
746 | writeln!( | |
747 | out, | |
748 | "hash {} stable_crate_id {:?}", | |
749 | root.hash(), | |
750 | root.stable_crate_id | |
751 | )?; | |
752 | writeln!(out, "proc_macro {:?}", root.proc_macro_data.is_some())?; | |
753 | writeln!(out, "triple {}", root.header.triple.triple())?; | |
754 | writeln!(out, "edition {}", root.edition)?; | |
755 | writeln!(out, "symbol_mangling_version {:?}", root.symbol_mangling_version)?; | |
756 | writeln!( | |
757 | out, | |
758 | "required_panic_strategy {:?} panic_in_drop_strategy {:?}", | |
759 | root.required_panic_strategy, root.panic_in_drop_strategy | |
760 | )?; | |
761 | writeln!( | |
762 | out, | |
763 | "has_global_allocator {} has_alloc_error_handler {} has_panic_handler {} has_default_lib_allocator {}", | |
764 | root.has_global_allocator, | |
765 | root.has_alloc_error_handler, | |
766 | root.has_panic_handler, | |
767 | root.has_default_lib_allocator | |
768 | )?; | |
769 | writeln!( | |
770 | out, | |
771 | "compiler_builtins {} needs_allocator {} needs_panic_runtime {} no_builtins {} panic_runtime {} profiler_runtime {}", | |
772 | root.compiler_builtins, | |
773 | root.needs_allocator, | |
774 | root.needs_panic_runtime, | |
775 | root.no_builtins, | |
776 | root.panic_runtime, | |
777 | root.profiler_runtime | |
778 | )?; | |
779 | ||
780 | writeln!(out, "=External Dependencies=")?; | |
781 | let dylib_dependency_formats = | |
782 | root.dylib_dependency_formats.decode(self).collect::<Vec<_>>(); | |
783 | for (i, dep) in root.crate_deps.decode(self).enumerate() { | |
784 | let CrateDep { name, extra_filename, hash, host_hash, kind, is_private } = | |
785 | dep; | |
786 | let number = i + 1; | |
787 | ||
788 | writeln!( | |
789 | out, | |
790 | "{number} {name}{extra_filename} hash {hash} host_hash {host_hash:?} kind {kind:?} {privacy}{linkage}", | |
791 | privacy = if is_private { "private" } else { "public" }, | |
792 | linkage = if dylib_dependency_formats.is_empty() { | |
793 | String::new() | |
794 | } else { | |
795 | format!(" linkage {:?}", dylib_dependency_formats[i]) | |
796 | } | |
797 | )?; | |
798 | } | |
799 | write!(out, "\n")?; | |
800 | } | |
801 | ||
802 | "lang_items" => { | |
803 | writeln!(out, "=Lang items=")?; | |
804 | for (id, lang_item) in root.lang_items.decode(self) { | |
805 | writeln!( | |
806 | out, | |
807 | "{} = crate{}", | |
808 | lang_item.name(), | |
809 | DefPath::make(LOCAL_CRATE, id, |parent| root | |
810 | .tables | |
811 | .def_keys | |
812 | .get(self, parent) | |
813 | .unwrap() | |
814 | .decode(self)) | |
815 | .to_string_no_crate_verbose() | |
816 | )?; | |
817 | } | |
818 | for lang_item in root.lang_items_missing.decode(self) { | |
819 | writeln!(out, "{} = <missing>", lang_item.name())?; | |
820 | } | |
821 | write!(out, "\n")?; | |
822 | } | |
823 | ||
824 | "features" => { | |
825 | writeln!(out, "=Lib features=")?; | |
826 | for (feature, since) in root.lib_features.decode(self) { | |
827 | writeln!( | |
828 | out, | |
829 | "{}{}", | |
830 | feature, | |
831 | if let Some(since) = since { | |
832 | format!(" since {since}") | |
833 | } else { | |
834 | String::new() | |
835 | } | |
836 | )?; | |
837 | } | |
838 | write!(out, "\n")?; | |
839 | } | |
840 | ||
841 | "items" => { | |
842 | writeln!(out, "=Items=")?; | |
843 | ||
844 | fn print_item( | |
845 | blob: &MetadataBlob, | |
846 | out: &mut dyn io::Write, | |
847 | item: DefIndex, | |
848 | indent: usize, | |
849 | ) -> io::Result<()> { | |
850 | let root = blob.get_root(); | |
851 | ||
852 | let def_kind = root.tables.opt_def_kind.get(blob, item).unwrap(); | |
853 | let def_key = root.tables.def_keys.get(blob, item).unwrap().decode(blob); | |
854 | let def_name = if item == CRATE_DEF_INDEX { | |
855 | rustc_span::symbol::kw::Crate | |
856 | } else { | |
857 | def_key | |
858 | .disambiguated_data | |
859 | .data | |
860 | .get_opt_name() | |
861 | .unwrap_or_else(|| Symbol::intern("???")) | |
862 | }; | |
863 | let visibility = | |
864 | root.tables.visibility.get(blob, item).unwrap().decode(blob).map_id( | |
865 | |index| { | |
866 | format!( | |
867 | "crate{}", | |
868 | DefPath::make(LOCAL_CRATE, index, |parent| root | |
869 | .tables | |
870 | .def_keys | |
871 | .get(blob, parent) | |
872 | .unwrap() | |
873 | .decode(blob)) | |
874 | .to_string_no_crate_verbose() | |
875 | ) | |
876 | }, | |
877 | ); | |
878 | write!( | |
879 | out, | |
880 | "{nil: <indent$}{:?} {:?} {} {{", | |
881 | visibility, | |
882 | def_kind, | |
883 | def_name, | |
884 | nil = "", | |
885 | )?; | |
886 | ||
887 | if let Some(children) = | |
888 | root.tables.module_children_non_reexports.get(blob, item) | |
889 | { | |
890 | write!(out, "\n")?; | |
891 | for child in children.decode(blob) { | |
892 | print_item(blob, out, child, indent + 4)?; | |
893 | } | |
894 | writeln!(out, "{nil: <indent$}}}", nil = "")?; | |
895 | } else { | |
896 | writeln!(out, "}}")?; | |
897 | } | |
898 | ||
899 | Ok(()) | |
900 | } | |
901 | ||
902 | print_item(self, out, CRATE_DEF_INDEX, 0)?; | |
903 | ||
904 | write!(out, "\n")?; | |
905 | } | |
906 | ||
907 | _ => { | |
908 | writeln!( | |
909 | out, | |
910 | "unknown -Zls kind. allowed values are: all, root, lang_items, features, items" | |
911 | )?; | |
912 | } | |
913 | } | |
1a4d82fc | 914 | } |
781aab86 | 915 | |
9e0c209e | 916 | Ok(()) |
970d7e83 | 917 | } |
223e47cc LB |
918 | } |
919 | ||
923072b8 FG |
920 | impl CrateRoot { |
921 | pub(crate) fn is_proc_macro_crate(&self) -> bool { | |
60c5eb7d XL |
922 | self.proc_macro_data.is_some() |
923 | } | |
924 | ||
923072b8 | 925 | pub(crate) fn name(&self) -> Symbol { |
fe692bf9 | 926 | self.header.name |
60c5eb7d XL |
927 | } |
928 | ||
923072b8 | 929 | pub(crate) fn hash(&self) -> Svh { |
fe692bf9 | 930 | self.header.hash |
60c5eb7d XL |
931 | } |
932 | ||
923072b8 | 933 | pub(crate) fn stable_crate_id(&self) -> StableCrateId { |
6a06907d XL |
934 | self.stable_crate_id |
935 | } | |
936 | ||
923072b8 | 937 | pub(crate) fn decode_crate_deps<'a>( |
60c5eb7d XL |
938 | &self, |
939 | metadata: &'a MetadataBlob, | |
940 | ) -> impl ExactSizeIterator<Item = CrateDep> + Captures<'a> { | |
941 | self.crate_deps.decode(metadata) | |
942 | } | |
943 | } | |
944 | ||
74b04a01 | 945 | impl<'a, 'tcx> CrateMetadataRef<'a> { |
353b0b11 FG |
946 | fn missing(self, descr: &str, id: DefIndex) -> ! { |
947 | bug!("missing `{descr}` for {:?}", self.local_def_id(id)) | |
948 | } | |
949 | ||
5099ac24 | 950 | fn raw_proc_macro(self, id: DefIndex) -> &'a ProcMacro { |
e1599b0c XL |
951 | // DefIndex's in root.proc_macro_data have a one-to-one correspondence |
952 | // with items in 'raw_proc_macros'. | |
1b1a35ee XL |
953 | let pos = self |
954 | .root | |
955 | .proc_macro_data | |
956 | .as_ref() | |
957 | .unwrap() | |
958 | .macros | |
959 | .decode(self) | |
960 | .position(|i| i == id) | |
961 | .unwrap(); | |
e1599b0c XL |
962 | &self.raw_proc_macros.unwrap()[pos] |
963 | } | |
964 | ||
5e7ed085 | 965 | fn opt_item_name(self, item_index: DefIndex) -> Option<Symbol> { |
2b03887a FG |
966 | let def_key = self.def_key(item_index); |
967 | def_key.disambiguated_data.data.get_opt_name().or_else(|| { | |
968 | if def_key.disambiguated_data.data == DefPathData::Ctor { | |
969 | let parent_index = def_key.parent.expect("no parent for a constructor"); | |
970 | self.def_key(parent_index).disambiguated_data.data.get_opt_name() | |
971 | } else { | |
972 | None | |
973 | } | |
974 | }) | |
5e7ed085 FG |
975 | } |
976 | ||
977 | fn item_name(self, item_index: DefIndex) -> Symbol { | |
978 | self.opt_item_name(item_index).expect("no encoded ident for item") | |
979 | } | |
980 | ||
5099ac24 | 981 | fn opt_item_ident(self, item_index: DefIndex, sess: &Session) -> Option<Ident> { |
5e7ed085 | 982 | let name = self.opt_item_name(item_index)?; |
353b0b11 FG |
983 | let span = self |
984 | .root | |
985 | .tables | |
986 | .def_ident_span | |
987 | .get(self, item_index) | |
988 | .unwrap_or_else(|| self.missing("def_ident_span", item_index)) | |
989 | .decode((self, sess)); | |
a2a8927a | 990 | Some(Ident::new(name, span)) |
223e47cc | 991 | } |
223e47cc | 992 | |
5099ac24 | 993 | fn item_ident(self, item_index: DefIndex, sess: &Session) -> Ident { |
a2a8927a | 994 | self.opt_item_ident(item_index, sess).expect("no encoded ident for item") |
5869c6ff XL |
995 | } |
996 | ||
04454e1e FG |
997 | #[inline] |
998 | pub(super) fn map_encoded_cnum_to_current(self, cnum: CrateNum) -> CrateNum { | |
999 | if cnum == LOCAL_CRATE { self.cnum } else { self.cnum_map[cnum] } | |
1000 | } | |
1001 | ||
5099ac24 | 1002 | fn def_kind(self, item_id: DefIndex) -> DefKind { |
04454e1e FG |
1003 | self.root.tables.opt_def_kind.get(self, item_id).unwrap_or_else(|| { |
1004 | bug!( | |
1005 | "CrateMetadata::def_kind({:?}): id not found, in crate {:?} with number {}", | |
1006 | item_id, | |
fe692bf9 | 1007 | self.root.name(), |
04454e1e FG |
1008 | self.cnum, |
1009 | ) | |
1010 | }) | |
476ff2be SL |
1011 | } |
1012 | ||
5099ac24 | 1013 | fn get_span(self, index: DefIndex, sess: &Session) -> Span { |
1b1a35ee XL |
1014 | self.root |
1015 | .tables | |
5e7ed085 | 1016 | .def_span |
1b1a35ee | 1017 | .get(self, index) |
353b0b11 | 1018 | .unwrap_or_else(|| self.missing("def_span", index)) |
1b1a35ee | 1019 | .decode((self, sess)) |
e1599b0c XL |
1020 | } |
1021 | ||
add651ee | 1022 | fn load_proc_macro(self, id: DefIndex, tcx: TyCtxt<'tcx>) -> SyntaxExtension { |
136023e0 | 1023 | let (name, kind, helper_attrs) = match *self.raw_proc_macro(id) { |
e1599b0c XL |
1024 | ProcMacro::CustomDerive { trait_name, attributes, client } => { |
1025 | let helper_attrs = | |
1026 | attributes.iter().cloned().map(Symbol::intern).collect::<Vec<_>>(); | |
1027 | ( | |
1028 | trait_name, | |
923072b8 | 1029 | SyntaxExtensionKind::Derive(Box::new(DeriveProcMacro { client })), |
e1599b0c XL |
1030 | helper_attrs, |
1031 | ) | |
1032 | } | |
136023e0 XL |
1033 | ProcMacro::Attr { name, client } => { |
1034 | (name, SyntaxExtensionKind::Attr(Box::new(AttrProcMacro { client })), Vec::new()) | |
1035 | } | |
1036 | ProcMacro::Bang { name, client } => { | |
1037 | (name, SyntaxExtensionKind::Bang(Box::new(BangProcMacro { client })), Vec::new()) | |
1038 | } | |
e1599b0c | 1039 | }; |
e1599b0c | 1040 | |
add651ee | 1041 | let sess = tcx.sess; |
136023e0 | 1042 | let attrs: Vec<_> = self.get_item_attrs(id, sess).collect(); |
e1599b0c | 1043 | SyntaxExtension::new( |
3dfed10e | 1044 | sess, |
add651ee | 1045 | tcx.features(), |
e1599b0c | 1046 | kind, |
136023e0 | 1047 | self.get_span(id, sess), |
e1599b0c | 1048 | helper_attrs, |
e74abb32 | 1049 | self.root.edition, |
e1599b0c | 1050 | Symbol::intern(name), |
fc512014 | 1051 | &attrs, |
e1599b0c | 1052 | ) |
7453a54e SL |
1053 | } |
1054 | ||
49aad941 FG |
1055 | fn get_explicit_item_bounds( |
1056 | self, | |
1057 | index: DefIndex, | |
1058 | tcx: TyCtxt<'tcx>, | |
fe692bf9 | 1059 | ) -> ty::EarlyBinder<&'tcx [(ty::Clause<'tcx>, Span)]> { |
49aad941 FG |
1060 | let lazy = self.root.tables.explicit_item_bounds.get(self, index); |
1061 | let output = if lazy.is_default() { | |
1062 | &mut [] | |
1063 | } else { | |
1064 | tcx.arena.alloc_from_iter(lazy.decode((self, tcx))) | |
1065 | }; | |
fe692bf9 | 1066 | ty::EarlyBinder::bind(&*output) |
49aad941 FG |
1067 | } |
1068 | ||
353b0b11 FG |
1069 | fn get_variant( |
1070 | self, | |
1071 | kind: DefKind, | |
1072 | index: DefIndex, | |
1073 | parent_did: DefId, | |
1074 | ) -> (VariantIdx, ty::VariantDef) { | |
e74abb32 | 1075 | let adt_kind = match kind { |
f2b60f7d FG |
1076 | DefKind::Variant => ty::AdtKind::Enum, |
1077 | DefKind::Struct => ty::AdtKind::Struct, | |
1078 | DefKind::Union => ty::AdtKind::Union, | |
e74abb32 XL |
1079 | _ => bug!(), |
1080 | }; | |
1081 | ||
f2b60f7d FG |
1082 | let data = self.root.tables.variant_data.get(self, index).unwrap().decode(self); |
1083 | ||
dfeec247 XL |
1084 | let variant_did = |
1085 | if adt_kind == ty::AdtKind::Enum { Some(self.local_def_id(index)) } else { None }; | |
487cf647 | 1086 | let ctor = data.ctor.map(|(kind, index)| (kind, self.local_def_id(index))); |
0bf4aa26 | 1087 | |
353b0b11 FG |
1088 | ( |
1089 | data.idx, | |
1090 | ty::VariantDef::new( | |
1091 | self.item_name(index), | |
1092 | variant_did, | |
1093 | ctor, | |
1094 | data.discr, | |
49aad941 FG |
1095 | self.get_associated_item_or_field_def_ids(index) |
1096 | .map(|did| ty::FieldDef { | |
1097 | did, | |
1098 | name: self.item_name(did.index), | |
1099 | vis: self.get_visibility(did.index), | |
353b0b11 FG |
1100 | }) |
1101 | .collect(), | |
1102 | adt_kind, | |
1103 | parent_did, | |
1104 | false, | |
1105 | data.is_non_exhaustive, | |
1106 | ), | |
b7449926 | 1107 | ) |
c30ab7b3 SL |
1108 | } |
1109 | ||
5e7ed085 | 1110 | fn get_adt_def(self, item_id: DefIndex, tcx: TyCtxt<'tcx>) -> ty::AdtDef<'tcx> { |
f2b60f7d | 1111 | let kind = self.def_kind(item_id); |
9e0c209e | 1112 | let did = self.local_def_id(item_id); |
94b46f34 | 1113 | |
5e7ed085 | 1114 | let adt_kind = match kind { |
f2b60f7d FG |
1115 | DefKind::Enum => ty::AdtKind::Enum, |
1116 | DefKind::Struct => ty::AdtKind::Struct, | |
1117 | DefKind::Union => ty::AdtKind::Union, | |
8bb4bdeb XL |
1118 | _ => bug!("get_adt_def called on a non-ADT {:?}", did), |
1119 | }; | |
5e7ed085 | 1120 | let repr = self.root.tables.repr_options.get(self, item_id).unwrap().decode(self); |
94b46f34 | 1121 | |
353b0b11 | 1122 | let mut variants: Vec<_> = if let ty::AdtKind::Enum = adt_kind { |
dfeec247 | 1123 | self.root |
ba9703b0 | 1124 | .tables |
49aad941 | 1125 | .module_children_non_reexports |
dfeec247 | 1126 | .get(self, item_id) |
9ffffee4 | 1127 | .expect("variants are not encoded for an enum") |
c30ab7b3 | 1128 | .decode(self) |
2b03887a FG |
1129 | .filter_map(|index| { |
1130 | let kind = self.def_kind(index); | |
1131 | match kind { | |
1132 | DefKind::Ctor(..) => None, | |
353b0b11 | 1133 | _ => Some(self.get_variant(kind, index, did)), |
2b03887a FG |
1134 | } |
1135 | }) | |
c30ab7b3 SL |
1136 | .collect() |
1137 | } else { | |
353b0b11 | 1138 | std::iter::once(self.get_variant(kind, item_id, did)).collect() |
9e0c209e | 1139 | }; |
9cc50fc6 | 1140 | |
353b0b11 | 1141 | variants.sort_by_key(|(idx, _)| *idx); |
9cc50fc6 | 1142 | |
353b0b11 FG |
1143 | tcx.mk_adt_def( |
1144 | did, | |
1145 | adt_kind, | |
1146 | variants.into_iter().map(|(_, variant)| variant).collect(), | |
1147 | repr, | |
1148 | ) | |
9e0c209e | 1149 | } |
1a4d82fc | 1150 | |
353b0b11 | 1151 | fn get_visibility(self, id: DefIndex) -> Visibility<DefId> { |
f2b60f7d FG |
1152 | self.root |
1153 | .tables | |
1154 | .visibility | |
1155 | .get(self, id) | |
353b0b11 | 1156 | .unwrap_or_else(|| self.missing("visibility", id)) |
f2b60f7d FG |
1157 | .decode(self) |
1158 | .map_id(|index| self.local_def_id(index)) | |
9e0c209e | 1159 | } |
1a4d82fc | 1160 | |
5099ac24 | 1161 | fn get_trait_item_def_id(self, id: DefIndex) -> Option<DefId> { |
923072b8 | 1162 | self.root.tables.trait_item_def_id.get(self, id).map(|d| d.decode_from_cdata(self)) |
5099ac24 FG |
1163 | } |
1164 | ||
5099ac24 | 1165 | fn get_expn_that_defined(self, id: DefIndex, sess: &Session) -> ExpnId { |
353b0b11 FG |
1166 | self.root |
1167 | .tables | |
1168 | .expn_that_defined | |
1169 | .get(self, id) | |
1170 | .unwrap_or_else(|| self.missing("expn_that_defined", id)) | |
1171 | .decode((self, sess)) | |
29967ef6 XL |
1172 | } |
1173 | ||
49aad941 | 1174 | fn get_debugger_visualizers(self) -> Vec<DebuggerVisualizerFile> { |
04454e1e FG |
1175 | self.root.debugger_visualizers.decode(self).collect::<Vec<_>>() |
1176 | } | |
1177 | ||
b7449926 | 1178 | /// Iterates over all the stability attributes in the given crate. |
5099ac24 | 1179 | fn get_lib_features(self, tcx: TyCtxt<'tcx>) -> &'tcx [(Symbol, Option<Symbol>)] { |
dfeec247 | 1180 | tcx.arena.alloc_from_iter(self.root.lib_features.decode(self)) |
9e0c209e | 1181 | } |
223e47cc | 1182 | |
064997fb FG |
1183 | /// Iterates over the stability implications in the given crate (when a `#[unstable]` attribute |
1184 | /// has an `implied_by` meta item, then the mapping from the implied feature to the actual | |
1185 | /// feature is a stability implication). | |
1186 | fn get_stability_implications(self, tcx: TyCtxt<'tcx>) -> &'tcx [(Symbol, Symbol)] { | |
1187 | tcx.arena.alloc_from_iter(self.root.stability_implications.decode(self)) | |
1188 | } | |
1189 | ||
b7449926 | 1190 | /// Iterates over the language items in the given crate. |
487cf647 | 1191 | fn get_lang_items(self, tcx: TyCtxt<'tcx>) -> &'tcx [(DefId, LangItem)] { |
5e7ed085 FG |
1192 | tcx.arena.alloc_from_iter( |
1193 | self.root | |
1194 | .lang_items | |
1195 | .decode(self) | |
1196 | .map(move |(def_index, index)| (self.local_def_id(def_index), index)), | |
1197 | ) | |
b7449926 XL |
1198 | } |
1199 | ||
fe692bf9 FG |
1200 | fn get_stripped_cfg_items(self, cnum: CrateNum, tcx: TyCtxt<'tcx>) -> &'tcx [StrippedCfgItem] { |
1201 | let item_names = self | |
1202 | .root | |
1203 | .stripped_cfg_items | |
1204 | .decode((self, tcx)) | |
1205 | .map(|item| item.map_mod_id(|index| DefId { krate: cnum, index })); | |
1206 | tcx.arena.alloc_from_iter(item_names) | |
1207 | } | |
1208 | ||
e1599b0c | 1209 | /// Iterates over the diagnostic items in the given crate. |
5099ac24 FG |
1210 | fn get_diagnostic_items(self) -> DiagnosticItems { |
1211 | let mut id_to_name = FxHashMap::default(); | |
1212 | let name_to_id = self | |
1213 | .root | |
1214 | .diagnostic_items | |
1215 | .decode(self) | |
1216 | .map(|(name, def_index)| { | |
1217 | let id = self.local_def_id(def_index); | |
1218 | id_to_name.insert(id, name); | |
1219 | (name, id) | |
1220 | }) | |
1221 | .collect(); | |
1222 | DiagnosticItems { id_to_name, name_to_id } | |
e1599b0c XL |
1223 | } |
1224 | ||
487cf647 FG |
1225 | fn get_mod_child(self, id: DefIndex, sess: &Session) -> ModChild { |
1226 | let ident = self.item_ident(id, sess); | |
353b0b11 | 1227 | let res = Res::Def(self.def_kind(id), self.local_def_id(id)); |
487cf647 | 1228 | let vis = self.get_visibility(id); |
487cf647 | 1229 | |
49aad941 | 1230 | ModChild { ident, res, vis, reexport_chain: Default::default() } |
487cf647 FG |
1231 | } |
1232 | ||
5099ac24 FG |
1233 | /// Iterates over all named children of the given module, |
1234 | /// including both proper items and reexports. | |
1235 | /// Module here is understood in name resolution sense - it can be a `mod` item, | |
1236 | /// or a crate root, or an enum, or a trait. | |
487cf647 | 1237 | fn get_module_children( |
5099ac24 FG |
1238 | self, |
1239 | id: DefIndex, | |
487cf647 FG |
1240 | sess: &'a Session, |
1241 | ) -> impl Iterator<Item = ModChild> + 'a { | |
ed00b5ec | 1242 | iter::from_coroutine(move || { |
487cf647 FG |
1243 | if let Some(data) = &self.root.proc_macro_data { |
1244 | // If we are loading as a proc macro, we want to return | |
1245 | // the view of this crate as a proc macro crate. | |
1246 | if id == CRATE_DEF_INDEX { | |
1247 | for child_index in data.macros.decode(self) { | |
1248 | yield self.get_mod_child(child_index, sess); | |
f2b60f7d | 1249 | } |
487cf647 FG |
1250 | } |
1251 | } else { | |
1252 | // Iterate over all children. | |
49aad941 FG |
1253 | let non_reexports = self.root.tables.module_children_non_reexports.get(self, id); |
1254 | for child_index in non_reexports.unwrap().decode(self) { | |
1255 | yield self.get_mod_child(child_index, sess); | |
487cf647 | 1256 | } |
04454e1e | 1257 | |
353b0b11 FG |
1258 | let reexports = self.root.tables.module_children_reexports.get(self, id); |
1259 | if !reexports.is_default() { | |
487cf647 FG |
1260 | for reexport in reexports.decode((self, sess)) { |
1261 | yield reexport; | |
04454e1e | 1262 | } |
d9579d0f AL |
1263 | } |
1264 | } | |
487cf647 | 1265 | }) |
9e0c209e | 1266 | } |
1a4d82fc | 1267 | |
5099ac24 | 1268 | fn is_ctfe_mir_available(self, id: DefIndex) -> bool { |
5869c6ff XL |
1269 | self.root.tables.mir_for_ctfe.get(self, id).is_some() |
1270 | } | |
1271 | ||
5099ac24 | 1272 | fn is_item_mir_available(self, id: DefIndex) -> bool { |
5e7ed085 | 1273 | self.root.tables.optimized_mir.get(self, id).is_some() |
9e0c209e | 1274 | } |
1a4d82fc | 1275 | |
ed00b5ec FG |
1276 | fn cross_crate_inlinable(self, id: DefIndex) -> bool { |
1277 | self.root.tables.cross_crate_inlinable.get(self, id).unwrap_or(false) | |
1278 | } | |
1279 | ||
f2b60f7d FG |
1280 | fn get_fn_has_self_parameter(self, id: DefIndex, sess: &'a Session) -> bool { |
1281 | self.root | |
1282 | .tables | |
1283 | .fn_arg_names | |
1284 | .get(self, id) | |
9ffffee4 | 1285 | .expect("argument names not encoded for a function") |
f2b60f7d FG |
1286 | .decode((self, sess)) |
1287 | .nth(0) | |
49aad941 | 1288 | .is_some_and(|ident| ident.name == kw::SelfLower) |
a2a8927a XL |
1289 | } |
1290 | ||
49aad941 | 1291 | fn get_associated_item_or_field_def_ids( |
04454e1e FG |
1292 | self, |
1293 | id: DefIndex, | |
04454e1e FG |
1294 | ) -> impl Iterator<Item = DefId> + 'a { |
1295 | self.root | |
1296 | .tables | |
49aad941 | 1297 | .associated_item_or_field_def_ids |
04454e1e | 1298 | .get(self, id) |
49aad941 FG |
1299 | .unwrap_or_else(|| self.missing("associated_item_or_field_def_ids", id)) |
1300 | .decode(self) | |
04454e1e | 1301 | .map(move |child_index| self.local_def_id(child_index)) |
5099ac24 FG |
1302 | } |
1303 | ||
f2b60f7d | 1304 | fn get_associated_item(self, id: DefIndex, sess: &'a Session) -> ty::AssocItem { |
353b0b11 FG |
1305 | let name = if self.root.tables.opt_rpitit_info.get(self, id).is_some() { |
1306 | kw::Empty | |
1307 | } else { | |
1308 | self.item_name(id) | |
1309 | }; | |
9ffffee4 FG |
1310 | let (kind, has_self) = match self.def_kind(id) { |
1311 | DefKind::AssocConst => (ty::AssocKind::Const, false), | |
1312 | DefKind::AssocFn => (ty::AssocKind::Fn, self.get_fn_has_self_parameter(id, sess)), | |
1313 | DefKind::AssocTy => (ty::AssocKind::Type, false), | |
f2b60f7d | 1314 | _ => bug!("cannot get associated-item of `{:?}`", self.def_key(id)), |
8bb4bdeb | 1315 | }; |
f2b60f7d | 1316 | let container = self.root.tables.assoc_container.get(self, id).unwrap(); |
353b0b11 FG |
1317 | let opt_rpitit_info = |
1318 | self.root.tables.opt_rpitit_info.get(self, id).map(|d| d.decode(self)); | |
8bb4bdeb | 1319 | |
dc9dc135 | 1320 | ty::AssocItem { |
5e7ed085 | 1321 | name, |
3b2f2976 | 1322 | kind, |
8bb4bdeb | 1323 | def_id: self.local_def_id(id), |
5099ac24 | 1324 | trait_item_def_id: self.get_trait_item_def_id(id), |
064997fb | 1325 | container, |
ba9703b0 | 1326 | fn_has_self_parameter: has_self, |
353b0b11 | 1327 | opt_rpitit_info, |
8bb4bdeb | 1328 | } |
9e0c209e | 1329 | } |
223e47cc | 1330 | |
487cf647 | 1331 | fn get_ctor(self, node_id: DefIndex) -> Option<(CtorKind, DefId)> { |
f2b60f7d FG |
1332 | match self.def_kind(node_id) { |
1333 | DefKind::Struct | DefKind::Variant => { | |
1334 | let vdata = self.root.tables.variant_data.get(self, node_id).unwrap().decode(self); | |
487cf647 | 1335 | vdata.ctor.map(|(kind, index)| (kind, self.local_def_id(index))) |
9e0c209e | 1336 | } |
c30ab7b3 | 1337 | _ => None, |
9e0c209e | 1338 | } |
223e47cc LB |
1339 | } |
1340 | ||
fc512014 | 1341 | fn get_item_attrs( |
5099ac24 | 1342 | self, |
a2a8927a | 1343 | id: DefIndex, |
fc512014 XL |
1344 | sess: &'a Session, |
1345 | ) -> impl Iterator<Item = ast::Attribute> + 'a { | |
ba9703b0 XL |
1346 | self.root |
1347 | .tables | |
1348 | .attributes | |
a2a8927a XL |
1349 | .get(self, id) |
1350 | .unwrap_or_else(|| { | |
1351 | // Structure and variant constructors don't have any attributes encoded for them, | |
1352 | // but we assume that someone passing a constructor ID actually wants to look at | |
1353 | // the attributes on the corresponding struct or variant. | |
1354 | let def_key = self.def_key(id); | |
1355 | assert_eq!(def_key.disambiguated_data.data, DefPathData::Ctor); | |
1356 | let parent_id = def_key.parent.expect("no parent for a constructor"); | |
1357 | self.root | |
1358 | .tables | |
1359 | .attributes | |
1360 | .get(self, parent_id) | |
1361 | .expect("no encoded attributes for a structure or variant") | |
1362 | }) | |
ba9703b0 | 1363 | .decode((self, sess)) |
9e0c209e | 1364 | } |
223e47cc | 1365 | |
60c5eb7d | 1366 | fn get_inherent_implementations_for_type( |
5099ac24 | 1367 | self, |
dc9dc135 XL |
1368 | tcx: TyCtxt<'tcx>, |
1369 | id: DefIndex, | |
1370 | ) -> &'tcx [DefId] { | |
e74abb32 | 1371 | tcx.arena.alloc_from_iter( |
dfeec247 | 1372 | self.root |
ba9703b0 | 1373 | .tables |
dfeec247 XL |
1374 | .inherent_impls |
1375 | .get(self, id) | |
e74abb32 | 1376 | .decode(self) |
dfeec247 | 1377 | .map(|index| self.local_def_id(index)), |
e74abb32 | 1378 | ) |
9e0c209e | 1379 | } |
223e47cc | 1380 | |
5099ac24 FG |
1381 | /// Decodes all traits in the crate (for rustdoc and rustc diagnostics). |
1382 | fn get_traits(self) -> impl Iterator<Item = DefId> + 'a { | |
1383 | self.root.traits.decode(self).map(move |index| self.local_def_id(index)) | |
1384 | } | |
1385 | ||
1386 | /// Decodes all trait impls in the crate (for rustdoc). | |
9ffffee4 FG |
1387 | fn get_trait_impls(self) -> impl Iterator<Item = DefId> + 'a { |
1388 | self.cdata.trait_impls.values().flat_map(move |impls| { | |
1389 | impls.decode(self).map(move |(impl_index, _)| self.local_def_id(impl_index)) | |
a2a8927a XL |
1390 | }) |
1391 | } | |
1392 | ||
5e7ed085 FG |
1393 | fn get_incoherent_impls(self, tcx: TyCtxt<'tcx>, simp: SimplifiedType) -> &'tcx [DefId] { |
1394 | if let Some(impls) = self.cdata.incoherent_impls.get(&simp) { | |
1395 | tcx.arena.alloc_from_iter(impls.decode(self).map(|idx| self.local_def_id(idx))) | |
1396 | } else { | |
1397 | &[] | |
1398 | } | |
1399 | } | |
1400 | ||
a2a8927a | 1401 | fn get_implementations_of_trait( |
5099ac24 | 1402 | self, |
dc9dc135 | 1403 | tcx: TyCtxt<'tcx>, |
a2a8927a XL |
1404 | trait_def_id: DefId, |
1405 | ) -> &'tcx [(DefId, Option<SimplifiedType>)] { | |
5099ac24 | 1406 | if self.trait_impls.is_empty() { |
dfeec247 | 1407 | return &[]; |
b7449926 XL |
1408 | } |
1409 | ||
a2a8927a XL |
1410 | // Do a reverse lookup beforehand to avoid touching the crate_num |
1411 | // hash map in the loop below. | |
1412 | let key = match self.reverse_translate_def_id(trait_def_id) { | |
1413 | Some(def_id) => (def_id.krate.as_u32(), def_id.index), | |
1414 | None => return &[], | |
1415 | }; | |
223e47cc | 1416 | |
a2a8927a XL |
1417 | if let Some(impls) = self.trait_impls.get(&key) { |
1418 | tcx.arena.alloc_from_iter( | |
3dfed10e XL |
1419 | impls |
1420 | .decode(self) | |
a2a8927a XL |
1421 | .map(|(idx, simplified_self_ty)| (self.local_def_id(idx), simplified_self_ty)), |
1422 | ) | |
1423 | } else { | |
1424 | &[] | |
9e0c209e SL |
1425 | } |
1426 | } | |
223e47cc | 1427 | |
5099ac24 FG |
1428 | fn get_native_libraries(self, sess: &'a Session) -> impl Iterator<Item = NativeLib> + 'a { |
1429 | self.root.native_libraries.decode((self, sess)) | |
223e47cc LB |
1430 | } |
1431 | ||
5099ac24 | 1432 | fn get_proc_macro_quoted_span(self, index: usize, sess: &Session) -> Span { |
17df50a5 XL |
1433 | self.root |
1434 | .tables | |
1435 | .proc_macro_quoted_spans | |
1436 | .get(self, index) | |
9c376795 | 1437 | .unwrap_or_else(|| panic!("Missing proc macro quoted span: {index:?}")) |
17df50a5 XL |
1438 | .decode((self, sess)) |
1439 | } | |
1440 | ||
5099ac24 FG |
1441 | fn get_foreign_modules(self, sess: &'a Session) -> impl Iterator<Item = ForeignModule> + '_ { |
1442 | self.root.foreign_modules.decode((self, sess)) | |
0531ce1d XL |
1443 | } |
1444 | ||
60c5eb7d | 1445 | fn get_dylib_dependency_formats( |
5099ac24 | 1446 | self, |
dc9dc135 XL |
1447 | tcx: TyCtxt<'tcx>, |
1448 | ) -> &'tcx [(CrateNum, LinkagePreference)] { | |
dfeec247 XL |
1449 | tcx.arena.alloc_from_iter( |
1450 | self.root.dylib_dependency_formats.decode(self).enumerate().flat_map(|(i, link)| { | |
c30ab7b3 | 1451 | let cnum = CrateNum::new(i + 1); |
94b46f34 | 1452 | link.map(|link| (self.cnum_map[cnum], link)) |
dfeec247 XL |
1453 | }), |
1454 | ) | |
223e47cc | 1455 | } |
223e47cc | 1456 | |
487cf647 | 1457 | fn get_missing_lang_items(self, tcx: TyCtxt<'tcx>) -> &'tcx [LangItem] { |
5099ac24 | 1458 | tcx.arena.alloc_from_iter(self.root.lang_items_missing.decode(self)) |
d9579d0f AL |
1459 | } |
1460 | ||
60c5eb7d | 1461 | fn exported_symbols( |
5099ac24 | 1462 | self, |
dc9dc135 | 1463 | tcx: TyCtxt<'tcx>, |
04454e1e | 1464 | ) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] { |
5099ac24 | 1465 | tcx.arena.alloc_from_iter(self.root.exported_symbols.decode((self, tcx))) |
83c7162d XL |
1466 | } |
1467 | ||
5e7ed085 | 1468 | fn get_macro(self, id: DefIndex, sess: &Session) -> ast::MacroDef { |
f2b60f7d FG |
1469 | match self.def_kind(id) { |
1470 | DefKind::Macro(_) => { | |
9ffffee4 | 1471 | let macro_rules = self.root.tables.is_macro_rules.get(self, id); |
f2b60f7d FG |
1472 | let body = |
1473 | self.root.tables.macro_definition.get(self, id).unwrap().decode((self, sess)); | |
1474 | ast::MacroDef { macro_rules, body: ast::ptr::P(body) } | |
5e7ed085 | 1475 | } |
476ff2be SL |
1476 | _ => bug!(), |
1477 | } | |
9e0c209e | 1478 | } |
9cc50fc6 | 1479 | |
cc61c64b | 1480 | #[inline] |
5099ac24 | 1481 | fn def_key(self, index: DefIndex) -> DefKey { |
fc512014 XL |
1482 | *self |
1483 | .def_key_cache | |
1484 | .lock() | |
1485 | .entry(index) | |
1486 | .or_insert_with(|| self.root.tables.def_keys.get(self, index).unwrap().decode(self)) | |
1487 | } | |
1488 | ||
32a655c1 | 1489 | // Returns the path leading to the thing with this `id`. |
5099ac24 | 1490 | fn def_path(self, id: DefIndex) -> DefPath { |
b7449926 | 1491 | debug!("def_path(cnum={:?}, id={:?})", self.cnum, id); |
e1599b0c | 1492 | DefPath::make(self.cnum, id, |parent| self.def_key(parent)) |
92a42be0 | 1493 | } |
92a42be0 | 1494 | |
3dfed10e | 1495 | fn def_path_hash_unlocked( |
5099ac24 | 1496 | self, |
3dfed10e XL |
1497 | index: DefIndex, |
1498 | def_path_hashes: &mut FxHashMap<DefIndex, DefPathHash>, | |
1499 | ) -> DefPathHash { | |
04454e1e FG |
1500 | *def_path_hashes |
1501 | .entry(index) | |
9ffffee4 | 1502 | .or_insert_with(|| self.root.tables.def_path_hashes.get(self, index)) |
3dfed10e XL |
1503 | } |
1504 | ||
1505 | #[inline] | |
5099ac24 | 1506 | fn def_path_hash(self, index: DefIndex) -> DefPathHash { |
3dfed10e XL |
1507 | let mut def_path_hashes = self.def_path_hash_cache.lock(); |
1508 | self.def_path_hash_unlocked(index, &mut def_path_hashes) | |
1509 | } | |
1510 | ||
c295e0f8 | 1511 | #[inline] |
5099ac24 | 1512 | fn def_path_hash_to_def_index(self, hash: DefPathHash) -> DefIndex { |
c295e0f8 XL |
1513 | self.def_path_hash_map.def_path_hash_to_def_index(&hash) |
1514 | } | |
1515 | ||
5099ac24 | 1516 | fn expn_hash_to_expn_id(self, sess: &Session, index_guess: u32, hash: ExpnHash) -> ExpnId { |
136023e0 XL |
1517 | debug_assert_eq!(ExpnId::from_hash(hash), None); |
1518 | let index_guess = ExpnIndex::from_u32(index_guess); | |
1519 | let old_hash = self.root.expn_hashes.get(self, index_guess).map(|lazy| lazy.decode(self)); | |
1520 | ||
1521 | let index = if old_hash == Some(hash) { | |
1522 | // Fast path: the expn and its index is unchanged from the | |
1523 | // previous compilation session. There is no need to decode anything | |
1524 | // else. | |
1525 | index_guess | |
1526 | } else { | |
1527 | // Slow path: We need to find out the new `DefIndex` of the provided | |
1528 | // `DefPathHash`, if its still exists. This requires decoding every `DefPathHash` | |
1529 | // stored in this crate. | |
1530 | let map = self.cdata.expn_hash_map.get_or_init(|| { | |
1531 | let end_id = self.root.expn_hashes.size() as u32; | |
1532 | let mut map = | |
1533 | UnhashMap::with_capacity_and_hasher(end_id as usize, Default::default()); | |
1534 | for i in 0..end_id { | |
1535 | let i = ExpnIndex::from_u32(i); | |
1536 | if let Some(hash) = self.root.expn_hashes.get(self, i) { | |
1537 | map.insert(hash.decode(self), i); | |
136023e0 XL |
1538 | } |
1539 | } | |
1540 | map | |
1541 | }); | |
1542 | map[&hash] | |
1543 | }; | |
1544 | ||
c295e0f8 | 1545 | let data = self.root.expn_data.get(self, index).unwrap().decode((self, sess)); |
136023e0 XL |
1546 | rustc_span::hygiene::register_expn_id(self.cnum, index, data, hash) |
1547 | } | |
1548 | ||
b7449926 | 1549 | /// Imports the source_map from an external crate into the source_map of the crate |
9e0c209e SL |
1550 | /// currently being compiled (the "local crate"). |
1551 | /// | |
1552 | /// The import algorithm works analogous to how AST items are inlined from an | |
1553 | /// external crate's metadata: | |
b7449926 XL |
1554 | /// For every SourceFile in the external source_map an 'inline' copy is created in the |
1555 | /// local source_map. The correspondence relation between external and local | |
1556 | /// SourceFiles is recorded in the `ImportedSourceFile` objects returned from this | |
9e0c209e SL |
1557 | /// function. When an item from an external crate is later inlined into this |
1558 | /// crate, this correspondence information is used to translate the span | |
1559 | /// information of the inlined item so that it refers the correct positions in | |
b7449926 | 1560 | /// the local source_map (see `<decoder::DecodeContext as SpecializedDecoder<Span>>`). |
9e0c209e | 1561 | /// |
b7449926 XL |
1562 | /// The import algorithm in the function below will reuse SourceFiles already |
1563 | /// existing in the local source_map. For example, even if the SourceFile of some | |
9e0c209e | 1564 | /// source file of libstd gets imported many times, there will only ever be |
b7449926 | 1565 | /// one SourceFile object for the corresponding file in the local source_map. |
9e0c209e | 1566 | /// |
b7449926 | 1567 | /// Note that imported SourceFiles do not actually contain the source code of the |
9e0c209e SL |
1568 | /// file they represent, just information about length, line breaks, and |
1569 | /// multibyte characters. This information is enough to generate valid debuginfo | |
1570 | /// for items inlined from other crates. | |
b7449926 XL |
1571 | /// |
1572 | /// Proc macro crates don't currently export spans, so this function does not have | |
1573 | /// to work for them. | |
f2b60f7d | 1574 | fn imported_source_file(self, source_file_index: u32, sess: &Session) -> ImportedSourceFile { |
064997fb FG |
1575 | fn filter<'a>(sess: &Session, path: Option<&'a Path>) -> Option<&'a Path> { |
1576 | path.filter(|_| { | |
ba9703b0 | 1577 | // Only spend time on further checks if we have what to translate *to*. |
cdc7bbd5 | 1578 | sess.opts.real_rust_source_base_dir.is_some() |
064997fb FG |
1579 | // Some tests need the translation to be always skipped. |
1580 | && sess.opts.unstable_opts.translate_remapped_path_to_local_path | |
ba9703b0 XL |
1581 | }) |
1582 | .filter(|virtual_dir| { | |
1583 | // Don't translate away `/rustc/$hash` if we're still remapping to it, | |
1584 | // since that means we're still building `std`/`rustc` that need it, | |
1585 | // and we don't want the real path to leak into codegen/debuginfo. | |
1586 | !sess.opts.remap_path_prefix.iter().any(|(_from, to)| to == virtual_dir) | |
064997fb FG |
1587 | }) |
1588 | } | |
1589 | ||
1590 | // Translate the virtual `/rustc/$hash` prefix back to a real directory | |
1591 | // that should hold actual sources, where possible. | |
1592 | // | |
1593 | // NOTE: if you update this, you might need to also update bootstrap's code for generating | |
1594 | // the `rust-src` component in `Src::run` in `src/bootstrap/dist.rs`. | |
1595 | let virtual_rust_source_base_dir = [ | |
1596 | filter(sess, option_env!("CFG_VIRTUAL_RUST_SOURCE_BASE_DIR").map(Path::new)), | |
1597 | filter(sess, sess.opts.unstable_opts.simulate_remapped_rust_src_base.as_deref()), | |
1598 | ]; | |
1599 | ||
ba9703b0 XL |
1600 | let try_to_translate_virtual_to_real = |name: &mut rustc_span::FileName| { |
1601 | debug!( | |
1602 | "try_to_translate_virtual_to_real(name={:?}): \ | |
1603 | virtual_rust_source_base_dir={:?}, real_rust_source_base_dir={:?}", | |
cdc7bbd5 | 1604 | name, virtual_rust_source_base_dir, sess.opts.real_rust_source_base_dir, |
ba9703b0 XL |
1605 | ); |
1606 | ||
064997fb | 1607 | for virtual_dir in virtual_rust_source_base_dir.iter().flatten() { |
cdc7bbd5 | 1608 | if let Some(real_dir) = &sess.opts.real_rust_source_base_dir { |
ba9703b0 | 1609 | if let rustc_span::FileName::Real(old_name) = name { |
17df50a5 XL |
1610 | if let rustc_span::RealFileName::Remapped { local_path: _, virtual_name } = |
1611 | old_name | |
1612 | { | |
1613 | if let Ok(rest) = virtual_name.strip_prefix(virtual_dir) { | |
1614 | let virtual_name = virtual_name.clone(); | |
3dfed10e XL |
1615 | |
1616 | // The std library crates are in | |
1617 | // `$sysroot/lib/rustlib/src/rust/library`, whereas other crates | |
1618 | // may be in `$sysroot/lib/rustlib/src/rust/` directly. So we | |
1619 | // detect crates from the std libs and handle them specially. | |
1620 | const STD_LIBS: &[&str] = &[ | |
1621 | "core", | |
1622 | "alloc", | |
1623 | "std", | |
1624 | "test", | |
1625 | "term", | |
1626 | "unwind", | |
1627 | "proc_macro", | |
1628 | "panic_abort", | |
1629 | "panic_unwind", | |
1630 | "profiler_builtins", | |
1631 | "rtstartup", | |
1632 | "rustc-std-workspace-core", | |
1633 | "rustc-std-workspace-alloc", | |
1634 | "rustc-std-workspace-std", | |
1635 | "backtrace", | |
1636 | ]; | |
1637 | let is_std_lib = STD_LIBS.iter().any(|l| rest.starts_with(l)); | |
1638 | ||
1639 | let new_path = if is_std_lib { | |
1640 | real_dir.join("library").join(rest) | |
1641 | } else { | |
1642 | real_dir.join(rest) | |
1643 | }; | |
1644 | ||
ba9703b0 XL |
1645 | debug!( |
1646 | "try_to_translate_virtual_to_real: `{}` -> `{}`", | |
1647 | virtual_name.display(), | |
1648 | new_path.display(), | |
1649 | ); | |
17df50a5 XL |
1650 | let new_name = rustc_span::RealFileName::Remapped { |
1651 | local_path: Some(new_path), | |
ba9703b0 XL |
1652 | virtual_name, |
1653 | }; | |
1654 | *old_name = new_name; | |
1655 | } | |
1656 | } | |
1657 | } | |
1658 | } | |
1659 | } | |
1660 | }; | |
1661 | ||
f2b60f7d FG |
1662 | let mut import_info = self.cdata.source_map_import_info.lock(); |
1663 | for _ in import_info.len()..=(source_file_index as usize) { | |
1664 | import_info.push(None); | |
1665 | } | |
1666 | import_info[source_file_index as usize] | |
1667 | .get_or_insert_with(|| { | |
1668 | let source_file_to_import = self | |
1669 | .root | |
1670 | .source_map | |
1671 | .get(self, source_file_index) | |
1672 | .expect("missing source file") | |
1673 | .decode(self); | |
1674 | ||
1675 | // We can't reuse an existing SourceFile, so allocate a new one | |
1676 | // containing the information we need. | |
781aab86 | 1677 | let original_end_pos = source_file_to_import.end_position(); |
f2b60f7d FG |
1678 | let rustc_span::SourceFile { |
1679 | mut name, | |
1680 | src_hash, | |
781aab86 FG |
1681 | start_pos: original_start_pos, |
1682 | source_len, | |
f2b60f7d FG |
1683 | lines, |
1684 | multibyte_chars, | |
1685 | non_narrow_chars, | |
1686 | normalized_pos, | |
1687 | name_hash, | |
1688 | .. | |
1689 | } = source_file_to_import; | |
1690 | ||
49aad941 FG |
1691 | // If this file is under $sysroot/lib/rustlib/src/ |
1692 | // and the user wish to simulate remapping with -Z simulate-remapped-rust-src-base, | |
f2b60f7d FG |
1693 | // then we change `name` to a similar state as if the rust was bootstrapped |
1694 | // with `remap-debuginfo = true`. | |
1695 | // This is useful for testing so that tests about the effects of | |
1696 | // `try_to_translate_virtual_to_real` don't have to worry about how the | |
1697 | // compiler is bootstrapped. | |
1698 | if let Some(virtual_dir) = &sess.opts.unstable_opts.simulate_remapped_rust_src_base | |
ed00b5ec FG |
1699 | && let Some(real_dir) = &sess.opts.real_rust_source_base_dir |
1700 | && let rustc_span::FileName::Real(ref mut old_name) = name | |
1701 | { | |
49aad941 | 1702 | let relative_path = match old_name { |
ed00b5ec FG |
1703 | rustc_span::RealFileName::LocalPath(local) => { |
1704 | local.strip_prefix(real_dir).ok() | |
1705 | } | |
49aad941 | 1706 | rustc_span::RealFileName::Remapped { virtual_name, .. } => { |
ed00b5ec FG |
1707 | option_env!("CFG_VIRTUAL_RUST_SOURCE_BASE_DIR") |
1708 | .and_then(|virtual_dir| virtual_name.strip_prefix(virtual_dir).ok()) | |
49aad941 FG |
1709 | } |
1710 | }; | |
1711 | debug!(?relative_path, ?virtual_dir, "simulate_remapped_rust_src_base"); | |
1712 | for subdir in ["library", "compiler"] { | |
ed00b5ec FG |
1713 | if let Some(rest) = relative_path.and_then(|p| p.strip_prefix(subdir).ok()) |
1714 | { | |
49aad941 FG |
1715 | *old_name = rustc_span::RealFileName::Remapped { |
1716 | local_path: None, // FIXME: maybe we should preserve this? | |
1717 | virtual_name: virtual_dir.join(subdir).join(rest), | |
1718 | }; | |
1719 | break; | |
17df50a5 XL |
1720 | } |
1721 | } | |
f2b60f7d | 1722 | } |
17df50a5 | 1723 | |
f2b60f7d FG |
1724 | // If this file's path has been remapped to `/rustc/$hash`, |
1725 | // we might be able to reverse that (also see comments above, | |
1726 | // on `try_to_translate_virtual_to_real`). | |
1727 | try_to_translate_virtual_to_real(&mut name); | |
1728 | ||
f2b60f7d FG |
1729 | let local_version = sess.source_map().new_imported_source_file( |
1730 | name, | |
1731 | src_hash, | |
1732 | name_hash, | |
781aab86 | 1733 | source_len.to_u32(), |
f2b60f7d FG |
1734 | self.cnum, |
1735 | lines, | |
1736 | multibyte_chars, | |
1737 | non_narrow_chars, | |
1738 | normalized_pos, | |
f2b60f7d FG |
1739 | source_file_index, |
1740 | ); | |
1741 | debug!( | |
1742 | "CrateMetaData::imported_source_files alloc \ | |
781aab86 FG |
1743 | source_file {:?} original (start_pos {:?} source_len {:?}) \ |
1744 | translated (start_pos {:?} source_len {:?})", | |
f2b60f7d | 1745 | local_version.name, |
781aab86 FG |
1746 | original_start_pos, |
1747 | source_len, | |
f2b60f7d | 1748 | local_version.start_pos, |
781aab86 | 1749 | local_version.source_len |
f2b60f7d | 1750 | ); |
e74abb32 | 1751 | |
f2b60f7d | 1752 | ImportedSourceFile { |
781aab86 FG |
1753 | original_start_pos, |
1754 | original_end_pos, | |
f2b60f7d FG |
1755 | translated_source_file: local_version, |
1756 | } | |
1757 | }) | |
1758 | .clone() | |
e74abb32 | 1759 | } |
04454e1e | 1760 | |
9ffffee4 FG |
1761 | fn get_attr_flags(self, index: DefIndex) -> AttrFlags { |
1762 | self.root.tables.attr_flags.get(self, index) | |
04454e1e | 1763 | } |
923072b8 FG |
1764 | |
1765 | fn get_is_intrinsic(self, index: DefIndex) -> bool { | |
9ffffee4 FG |
1766 | self.root.tables.is_intrinsic.get(self, index) |
1767 | } | |
1768 | ||
1769 | fn get_doc_link_resolutions(self, index: DefIndex) -> DocLinkResMap { | |
1770 | self.root | |
1771 | .tables | |
1772 | .doc_link_resolutions | |
1773 | .get(self, index) | |
1774 | .expect("no resolutions for a doc link") | |
1775 | .decode(self) | |
1776 | } | |
1777 | ||
1778 | fn get_doc_link_traits_in_scope(self, index: DefIndex) -> impl Iterator<Item = DefId> + 'a { | |
1779 | self.root | |
1780 | .tables | |
1781 | .doc_link_traits_in_scope | |
1782 | .get(self, index) | |
1783 | .expect("no traits in scope for a doc link") | |
1784 | .decode(self) | |
923072b8 | 1785 | } |
74b04a01 | 1786 | } |
0531ce1d | 1787 | |
74b04a01 | 1788 | impl CrateMetadata { |
923072b8 | 1789 | pub(crate) fn new( |
74b04a01 | 1790 | sess: &Session, |
04454e1e | 1791 | cstore: &CStore, |
74b04a01 | 1792 | blob: MetadataBlob, |
923072b8 | 1793 | root: CrateRoot, |
74b04a01 XL |
1794 | raw_proc_macros: Option<&'static [ProcMacro]>, |
1795 | cnum: CrateNum, | |
1796 | cnum_map: CrateNumMap, | |
3dfed10e | 1797 | dep_kind: CrateDepKind, |
74b04a01 XL |
1798 | source: CrateSource, |
1799 | private_dep: bool, | |
1800 | host_hash: Option<Svh>, | |
1801 | ) -> CrateMetadata { | |
74b04a01 XL |
1802 | let trait_impls = root |
1803 | .impls | |
1804 | .decode((&blob, sess)) | |
1805 | .map(|trait_impls| (trait_impls.trait_id, trait_impls.impls)) | |
1806 | .collect(); | |
1807 | let alloc_decoding_state = | |
1808 | AllocDecodingState::new(root.interpret_alloc_index.decode(&blob).collect()); | |
353b0b11 | 1809 | let dependencies = cnum_map.iter().copied().collect(); |
c295e0f8 XL |
1810 | |
1811 | // Pre-decode the DefPathHash->DefIndex table. This is a cheap operation | |
1812 | // that does not copy any data. It just does some data verification. | |
1813 | let def_path_hash_map = root.def_path_hash_map.decode(&blob); | |
1814 | ||
04454e1e | 1815 | let mut cdata = CrateMetadata { |
74b04a01 XL |
1816 | blob, |
1817 | root, | |
74b04a01 | 1818 | trait_impls, |
04454e1e | 1819 | incoherent_impls: Default::default(), |
74b04a01 | 1820 | raw_proc_macros, |
f2b60f7d | 1821 | source_map_import_info: Lock::new(Vec::new()), |
c295e0f8 | 1822 | def_path_hash_map, |
136023e0 | 1823 | expn_hash_map: Default::default(), |
74b04a01 | 1824 | alloc_decoding_state, |
74b04a01 XL |
1825 | cnum, |
1826 | cnum_map, | |
1827 | dependencies, | |
1828 | dep_kind: Lock::new(dep_kind), | |
5099ac24 | 1829 | source: Lrc::new(source), |
fe692bf9 | 1830 | private_dep: AtomicBool::new(private_dep), |
74b04a01 XL |
1831 | host_hash, |
1832 | extern_crate: Lock::new(None), | |
3dfed10e XL |
1833 | hygiene_context: Default::default(), |
1834 | def_key_cache: Default::default(), | |
1835 | def_path_hash_cache: Default::default(), | |
04454e1e FG |
1836 | }; |
1837 | ||
1838 | // Need `CrateMetadataRef` to decode `DefId`s in simplified types. | |
1839 | cdata.incoherent_impls = cdata | |
1840 | .root | |
1841 | .incoherent_impls | |
1842 | .decode(CrateMetadataRef { cdata: &cdata, cstore }) | |
1843 | .map(|incoherent_impls| (incoherent_impls.self_ty, incoherent_impls.impls)) | |
1844 | .collect(); | |
1845 | ||
1846 | cdata | |
b039eaaf | 1847 | } |
60c5eb7d | 1848 | |
353b0b11 FG |
1849 | pub(crate) fn dependencies(&self) -> impl Iterator<Item = CrateNum> + '_ { |
1850 | self.dependencies.iter() | |
60c5eb7d XL |
1851 | } |
1852 | ||
923072b8 | 1853 | pub(crate) fn add_dependency(&self, cnum: CrateNum) { |
353b0b11 | 1854 | self.dependencies.push(cnum); |
60c5eb7d XL |
1855 | } |
1856 | ||
923072b8 | 1857 | pub(crate) fn update_extern_crate(&self, new_extern_crate: ExternCrate) -> bool { |
60c5eb7d XL |
1858 | let mut extern_crate = self.extern_crate.borrow_mut(); |
1859 | let update = Some(new_extern_crate.rank()) > extern_crate.as_ref().map(ExternCrate::rank); | |
1860 | if update { | |
1861 | *extern_crate = Some(new_extern_crate); | |
1862 | } | |
1863 | update | |
1864 | } | |
1865 | ||
923072b8 | 1866 | pub(crate) fn source(&self) -> &CrateSource { |
5099ac24 | 1867 | &*self.source |
60c5eb7d XL |
1868 | } |
1869 | ||
923072b8 | 1870 | pub(crate) fn dep_kind(&self) -> CrateDepKind { |
60c5eb7d XL |
1871 | *self.dep_kind.lock() |
1872 | } | |
1873 | ||
923072b8 | 1874 | pub(crate) fn update_dep_kind(&self, f: impl FnOnce(CrateDepKind) -> CrateDepKind) { |
60c5eb7d XL |
1875 | self.dep_kind.with_lock(|dep_kind| *dep_kind = f(*dep_kind)) |
1876 | } | |
1877 | ||
fe692bf9 FG |
1878 | pub(crate) fn update_and_private_dep(&self, private_dep: bool) { |
1879 | self.private_dep.fetch_and(private_dep, Ordering::SeqCst); | |
1880 | } | |
1881 | ||
064997fb FG |
1882 | pub(crate) fn required_panic_strategy(&self) -> Option<PanicStrategy> { |
1883 | self.root.required_panic_strategy | |
60c5eb7d XL |
1884 | } |
1885 | ||
923072b8 | 1886 | pub(crate) fn needs_panic_runtime(&self) -> bool { |
60c5eb7d XL |
1887 | self.root.needs_panic_runtime |
1888 | } | |
1889 | ||
923072b8 | 1890 | pub(crate) fn is_panic_runtime(&self) -> bool { |
60c5eb7d XL |
1891 | self.root.panic_runtime |
1892 | } | |
1893 | ||
923072b8 | 1894 | pub(crate) fn is_profiler_runtime(&self) -> bool { |
60c5eb7d XL |
1895 | self.root.profiler_runtime |
1896 | } | |
1897 | ||
923072b8 | 1898 | pub(crate) fn needs_allocator(&self) -> bool { |
60c5eb7d XL |
1899 | self.root.needs_allocator |
1900 | } | |
1901 | ||
923072b8 | 1902 | pub(crate) fn has_global_allocator(&self) -> bool { |
60c5eb7d XL |
1903 | self.root.has_global_allocator |
1904 | } | |
1905 | ||
487cf647 FG |
1906 | pub(crate) fn has_alloc_error_handler(&self) -> bool { |
1907 | self.root.has_alloc_error_handler | |
1908 | } | |
1909 | ||
923072b8 | 1910 | pub(crate) fn has_default_lib_allocator(&self) -> bool { |
60c5eb7d XL |
1911 | self.root.has_default_lib_allocator |
1912 | } | |
1913 | ||
923072b8 | 1914 | pub(crate) fn is_proc_macro_crate(&self) -> bool { |
60c5eb7d XL |
1915 | self.root.is_proc_macro_crate() |
1916 | } | |
1917 | ||
923072b8 | 1918 | pub(crate) fn name(&self) -> Symbol { |
fe692bf9 | 1919 | self.root.header.name |
60c5eb7d XL |
1920 | } |
1921 | ||
923072b8 | 1922 | pub(crate) fn hash(&self) -> Svh { |
fe692bf9 | 1923 | self.root.header.hash |
60c5eb7d | 1924 | } |
74b04a01 | 1925 | |
3dfed10e XL |
1926 | fn num_def_ids(&self) -> usize { |
1927 | self.root.tables.def_keys.size() | |
1928 | } | |
1929 | ||
74b04a01 XL |
1930 | fn local_def_id(&self, index: DefIndex) -> DefId { |
1931 | DefId { krate: self.cnum, index } | |
1932 | } | |
1933 | ||
1934 | // Translate a DefId from the current compilation environment to a DefId | |
1935 | // for an external crate. | |
1936 | fn reverse_translate_def_id(&self, did: DefId) -> Option<DefId> { | |
1937 | for (local, &global) in self.cnum_map.iter_enumerated() { | |
1938 | if global == did.krate { | |
1939 | return Some(DefId { krate: local, index: did.index }); | |
1940 | } | |
1941 | } | |
1942 | ||
1943 | None | |
1944 | } | |
a7813a04 | 1945 | } |