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