use rustc::middle::lang_items;
use rustc::mir::interpret::{AllocDecodingSession, AllocDecodingState};
use rustc::mir::{self, interpret, BodyAndCache, Promoted};
-use rustc::session::Session;
use rustc::ty::codec::TyDecoder;
use rustc::ty::{self, Ty, TyCtxt};
use rustc::util::common::record_time;
+use rustc_ast::ast::{self, Ident};
+use rustc_attr as attr;
use rustc_data_structures::captures::Captures;
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::svh::Svh;
use rustc_data_structures::sync::{AtomicCell, Lock, LockGuard, Lrc, Once};
+use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind};
+use rustc_expand::proc_macro::{AttrProcMacro, BangProcMacro, ProcMacroDerive};
use rustc_hir as hir;
use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
use rustc_index::vec::{Idx, IndexVec};
+use rustc_serialize::{opaque, Decodable, Decoder, SpecializedDecoder};
+use rustc_session::Session;
+use rustc_span::source_map::{self, respan, Spanned};
+use rustc_span::symbol::{sym, Symbol};
+use rustc_span::{self, hygiene::MacroKind, BytePos, Pos, Span, DUMMY_SP};
+use log::debug;
+use proc_macro::bridge::client::ProcMacro;
use std::io;
use std::mem;
use std::num::NonZeroUsize;
use std::u32;
-use log::debug;
-use proc_macro::bridge::client::ProcMacro;
-use rustc_ast::ast::{self, Ident};
-use rustc_attr as attr;
-use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind};
-use rustc_expand::proc_macro::{AttrProcMacro, BangProcMacro, ProcMacroDerive};
-use rustc_serialize::{opaque, Decodable, Decoder, SpecializedDecoder};
-use rustc_span::source_map::{self, respan, Spanned};
-use rustc_span::symbol::{sym, Symbol};
-use rustc_span::{self, hygiene::MacroKind, BytePos, Pos, Span, DUMMY_SP};
-
pub use cstore_impl::{provide, provide_extern};
mod cstore_impl;
impl<'a, 'tcx> SpecializedDecoder<LocalDefId> for DecodeContext<'a, 'tcx> {
#[inline]
fn specialized_decode(&mut self) -> Result<LocalDefId, Self::Error> {
- self.specialized_decode().map(|i| LocalDefId::from_def_id(i))
+ Ok(DefId::decode(self)?.expect_local())
}
}
return Ok(DUMMY_SP);
}
- debug_assert_eq!(tag, TAG_VALID_SPAN);
+ debug_assert!(tag == TAG_VALID_SPAN_LOCAL || tag == TAG_VALID_SPAN_FOREIGN);
let lo = BytePos::decode(self)?;
let len = BytePos::decode(self)?;
bug!("Cannot decode Span without Session.")
};
- let imported_source_files = self.cdata().imported_source_files(&sess.source_map());
+ // There are two possibilities here:
+ // 1. This is a 'local span', which is located inside a `SourceFile`
+ // that came from this crate. In this case, we use the source map data
+ // encoded in this crate. This branch should be taken nearly all of the time.
+ // 2. This is a 'foreign span', which is located inside a `SourceFile`
+ // that came from a *different* crate (some crate upstream of the one
+ // whose metadata we're looking at). For example, consider this dependency graph:
+ //
+ // A -> B -> C
+ //
+ // Suppose that we're currently compiling crate A, and start deserializing
+ // metadata from crate B. When we deserialize a Span from crate B's metadata,
+ // there are two posibilites:
+ //
+ // 1. The span references a file from crate B. This makes it a 'local' span,
+ // which means that we can use crate B's serialized source map information.
+ // 2. The span references a file from crate C. This makes it a 'foreign' span,
+ // which means we need to use Crate *C* (not crate B) to determine the source
+ // map information. We only record source map information for a file in the
+ // crate that 'owns' it, so deserializing a Span may require us to look at
+ // a transitive dependency.
+ //
+ // When we encode a foreign span, we adjust its 'lo' and 'high' values
+ // to be based on the *foreign* crate (e.g. crate C), not the crate
+ // we are writing metadata for (e.g. crate B). This allows us to
+ // treat the 'local' and 'foreign' cases almost identically during deserialization:
+ // we can call `imported_source_files` for the proper crate, and binary search
+ // through the returned slice using our span.
+ let imported_source_files = if tag == TAG_VALID_SPAN_LOCAL {
+ self.cdata().imported_source_files(sess.source_map())
+ } else {
+ // FIXME: We don't decode dependencies of proc-macros.
+ // Remove this once #69976 is merged
+ if self.cdata().root.is_proc_macro_crate() {
+ debug!(
+ "SpecializedDecoder<Span>::specialized_decode: skipping span for proc-macro crate {:?}",
+ self.cdata().cnum
+ );
+ // Decode `CrateNum` as u32 - using `CrateNum::decode` will ICE
+ // since we don't have `cnum_map` populated.
+ // This advances the decoder position so that we can continue
+ // to read metadata.
+ let _ = u32::decode(self)?;
+ return Ok(DUMMY_SP);
+ }
+ // tag is TAG_VALID_SPAN_FOREIGN, checked by `debug_assert` above
+ let cnum = CrateNum::decode(self)?;
+ debug!(
+ "SpecializedDecoder<Span>::specialized_decode: loading source files from cnum {:?}",
+ cnum
+ );
+
+ // Decoding 'foreign' spans should be rare enough that it's
+ // not worth it to maintain a per-CrateNum cache for `last_source_file_index`.
+ // We just set it to 0, to ensure that we don't try to access something out
+ // of bounds for our initial 'guess'
+ self.last_source_file_index = 0;
+
+ let foreign_data = self.cdata().cstore.get_crate_data(cnum);
+ foreign_data.imported_source_files(sess.source_map())
+ };
+
let source_file = {
// Optimize for the case that most spans within a translated item
// originate from the same source_file.
.binary_search_by_key(&lo, |source_file| source_file.original_start_pos)
.unwrap_or_else(|index| index - 1);
- self.last_source_file_index = index;
+ // Don't try to cache the index for foreign spans,
+ // as this would require a map from CrateNums to indices
+ if tag == TAG_VALID_SPAN_LOCAL {
+ self.last_source_file_index = index;
+ }
&imported_source_files[index]
}
};
// Make sure our binary search above is correct.
- debug_assert!(lo >= source_file.original_start_pos && lo <= source_file.original_end_pos);
+ debug_assert!(
+ lo >= source_file.original_start_pos && lo <= source_file.original_end_pos,
+ "Bad binary search: lo={:?} source_file.original_start_pos={:?} source_file.original_end_pos={:?}",
+ lo,
+ source_file.original_start_pos,
+ source_file.original_end_pos
+ );
// Make sure we correctly filtered out invalid spans during encoding
- debug_assert!(hi >= source_file.original_start_pos && hi <= source_file.original_end_pos);
+ debug_assert!(
+ hi >= source_file.original_start_pos && hi <= source_file.original_end_pos,
+ "Bad binary search: hi={:?} source_file.original_start_pos={:?} source_file.original_end_pos={:?}",
+ hi,
+ source_file.original_start_pos,
+ source_file.original_end_pos
+ );
let lo =
(lo + source_file.translated_source_file.start_pos) - source_file.original_start_pos;
data.paren_sugar,
data.has_auto_impl,
data.is_marker,
+ data.specialization_kind,
self.def_path_table.def_path_hash(item_id),
)
}
false,
false,
false,
+ ty::trait_def::TraitSpecializationKind::None,
self.def_path_table.def_path_hash(item_id),
),
_ => bug!("def-index does not refer to trait or trait alias"),
let local_version = local_source_map.new_imported_source_file(
name,
name_was_remapped,
- self.cnum.as_u32(),
src_hash,
name_hash,
source_length,
+ self.cnum,
lines,
multibyte_chars,
non_narrow_chars,
normalized_pos,
+ start_pos,
+ end_pos,
);
debug!(
"CrateMetaData::imported_source_files alloc \