Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add expansion info to crate metadata #43847

Closed
wants to merge 13 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/librustc_metadata/creader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,8 @@ impl<'a> CrateLoader<'a> {
// Initialize this with an empty set. The field is populated below
// after we were able to deserialize its contents.
dllimport_foreign_items: FxHashSet(),
hygiene_data_import_info: RefCell::new(None),
hygiene_data_being_decoded: Cell::new(false),
};

let dllimports: FxHashSet<_> = cmeta
Expand Down
5 changes: 4 additions & 1 deletion src/librustc_metadata/cstore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use owning_ref::ErasedBoxRef;
use syntax::{ast, attr};
use syntax::ext::base::SyntaxExtension;
use syntax::symbol::Symbol;
use syntax_pos;
use syntax_pos::{self, hygiene};

pub use rustc::middle::cstore::{NativeLibrary, NativeLibraryKind, LinkagePreference};
pub use rustc::middle::cstore::NativeLibraryKind::*;
Expand Down Expand Up @@ -87,6 +87,9 @@ pub struct CrateMetadata {
pub proc_macros: Option<Vec<(ast::Name, Rc<SyntaxExtension>)>>,
// Foreign items imported from a dylib (Windows only)
pub dllimport_foreign_items: FxHashSet<DefIndex>,

pub hygiene_data_import_info: RefCell<Option<hygiene::ImportedHygieneData>>,
pub hygiene_data_being_decoded: Cell<bool>,
}

pub struct CStore {
Expand Down
56 changes: 53 additions & 3 deletions src/librustc_metadata/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ use syntax::ast::{self, Ident};
use syntax::codemap;
use syntax::symbol::{InternedString, Symbol};
use syntax::ext::base::MacroKind;
use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP, NO_EXPANSION};
use syntax_pos::{self, hygiene, Span, SyntaxContext, BytePos, Pos, DUMMY_SP};

pub struct DecodeContext<'a, 'tcx: 'a> {
opaque: opaque::Decoder<'a>,
Expand Down Expand Up @@ -237,15 +237,44 @@ impl<'a, 'tcx> SpecializedDecoder<CrateNum> for DecodeContext<'a, 'tcx> {
}
}

impl<'a, 'tcx> SpecializedDecoder<hygiene::Mark> for DecodeContext<'a, 'tcx> {
fn specialized_decode(&mut self) -> Result<hygiene::Mark, Self::Error> {
let mark = u32::decode(self)?;

if !self.cdata().hygiene_data_being_decoded.get() && mark != 0 {
let imported_hygiene = self.cdata().imported_hygiene_data();

Ok(imported_hygiene.translate_mark(hygiene::Mark::from_u32(mark)))
} else {
Ok(hygiene::Mark::from_u32(mark))
}
}
}

impl<'a, 'tcx> SpecializedDecoder<SyntaxContext> for DecodeContext<'a, 'tcx> {
fn specialized_decode(&mut self) -> Result<SyntaxContext, Self::Error> {
let ctxt = u32::decode(self)?;

if !self.cdata().hygiene_data_being_decoded.get() && ctxt != 0 {
let imported_hygiene = self.cdata().imported_hygiene_data();

Ok(imported_hygiene.translate_ctxt(SyntaxContext::from_u32(ctxt)))
} else {
Ok(SyntaxContext::from_u32(ctxt))
}
}
}

impl<'a, 'tcx> SpecializedDecoder<Span> for DecodeContext<'a, 'tcx> {
fn specialized_decode(&mut self) -> Result<Span, Self::Error> {
let lo = BytePos::decode(self)?;
let hi = BytePos::decode(self)?;
let ctxt = SyntaxContext::decode(self)?;

let sess = if let Some(sess) = self.sess {
sess
} else {
return Ok(Span::new(lo, hi, NO_EXPANSION));
return Ok(Span::new(lo, hi, ctxt));
};

let (lo, hi) = if lo > hi {
Expand Down Expand Up @@ -292,7 +321,7 @@ impl<'a, 'tcx> SpecializedDecoder<Span> for DecodeContext<'a, 'tcx> {
let lo = (lo - filemap.original_start_pos) + filemap.translated_filemap.start_pos;
let hi = (hi - filemap.original_start_pos) + filemap.translated_filemap.start_pos;

Ok(Span::new(lo, hi, NO_EXPANSION))
Ok(Span::new(lo, hi, ctxt))
}
}

Expand Down Expand Up @@ -1224,4 +1253,25 @@ impl<'a, 'tcx> CrateMetadata {
*self.codemap_import_info.borrow_mut() = imported_filemaps;
self.codemap_import_info.borrow()
}

pub fn imported_hygiene_data(&'a self) -> Ref<'a, hygiene::ImportedHygieneData> {
{
let hygiene_data = self.hygiene_data_import_info.borrow();
if hygiene_data.is_some() {
return Ref::map(hygiene_data, |d| d.as_ref().unwrap());
}
}

self.hygiene_data_being_decoded.set(true);

let external_hygiene_data = self.root.hygiene_data.decode(self);

// This shouldn't borrow twice, but there is no way to downgrade RefMut to Ref.
*self.hygiene_data_import_info.borrow_mut() =
Some(hygiene::extend_hygiene_data(external_hygiene_data));

self.hygiene_data_being_decoded.set(false);

Ref::map(self.hygiene_data_import_info.borrow(), |d| d.as_ref().unwrap())
}
}
46 changes: 43 additions & 3 deletions src/librustc_metadata/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ use rustc::ty::{self, Ty, TyCtxt, ReprOptions};
use rustc::session::config::{self, CrateTypeProcMacro};
use rustc::util::nodemap::{FxHashMap, NodeSet};

use rustc_serialize::{Encodable, Encoder, SpecializedEncoder, opaque};
use rustc_serialize::{Encodable, Encoder, SpecializedEncoder, UseSpecializedEncodable, opaque};

use std::hash::Hash;
use std::intrinsics;
Expand All @@ -42,7 +42,7 @@ use syntax::ast::{self, CRATE_NODE_ID};
use syntax::codemap::Spanned;
use syntax::attr;
use syntax::symbol::Symbol;
use syntax_pos;
use syntax_pos::{self, hygiene};

use rustc::hir::{self, PatKind};
use rustc::hir::itemlikevisit::ItemLikeVisitor;
Expand All @@ -61,6 +61,13 @@ pub struct EncodeContext<'a, 'tcx: 'a> {

pub metadata_hashes: EncodedMetadataHashes,
pub compute_ich: bool,
// We need to encode hygiene info after all spans and possibly other data structures
// that reference it have been encoded already, since we only encode those elements of it
// that are actually used to avoid excessive memory usage. Thus, we need to keep track of
// whether we already encoded the hygiene info (and thus committed to a specific set of
// information to encode) to make sure we can catch bugs introduced by further changes
// quickly.
already_encoded_hygiene_data: bool,
}

macro_rules! encoder_methods {
Expand Down Expand Up @@ -136,6 +143,26 @@ impl<'a, 'tcx> SpecializedEncoder<ty::GenericPredicates<'tcx>> for EncodeContext
}
}

impl<'a, 'tcx> SpecializedEncoder<hygiene::SyntaxContext> for EncodeContext<'a, 'tcx> {
fn specialized_encode(&mut self, ctxt: &hygiene::SyntaxContext) -> Result<(), Self::Error> {
if self.already_encoded_hygiene_data {
bug!("trying to encode syntax context `{:?}` after encoding hygiene data!", ctxt);
} else {
ctxt.default_encode(self)
}
}
}

impl<'a, 'tcx> SpecializedEncoder<hygiene::Mark> for EncodeContext<'a, 'tcx> {
fn specialized_encode(&mut self, mark: &hygiene::Mark) -> Result<(), Self::Error> {
if self.already_encoded_hygiene_data {
bug!("trying to encode mark `{:?}` after encoding hygiene data!", mark);
} else {
mark.default_encode(self)
}
}
}

impl<'a, 'tcx> EncodeContext<'a, 'tcx> {

pub fn position(&self) -> usize {
Expand Down Expand Up @@ -323,6 +350,11 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
self.lazy_seq_ref(adapted.iter().map(|rc| &**rc))
}

fn encode_hygiene_data(&mut self) -> Lazy<hygiene::HygieneDataMap> {
let data = hygiene::HygieneData::safe_with(|data| data.to_map());
self.lazy(&data)
}

fn encode_crate_root(&mut self) -> Lazy<CrateRoot> {
let mut i = self.position();

Expand Down Expand Up @@ -397,6 +429,12 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
let index = items.write_index(&mut self.opaque.cursor);
let index_bytes = self.position() - i;

// Encode hygiene data
i = self.position();
let hygiene_data = self.encode_hygiene_data();
let hygiene_data_bytes = self.position() - i;
self.already_encoded_hygiene_data = true;

let tcx = self.tcx;
let link_meta = self.link_meta;
let is_proc_macro = tcx.sess.crate_types.borrow().contains(&CrateTypeProcMacro);
Expand All @@ -421,7 +459,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
} else {
None
},

crate_deps,
dylib_dependency_formats,
lang_items,
Expand All @@ -432,6 +469,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
impls,
exported_symbols,
index,
hygiene_data,
});

let total_bytes = self.position();
Expand Down Expand Up @@ -459,6 +497,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
println!(" def-path table bytes: {}", def_path_table_bytes);
println!(" item bytes: {}", item_bytes);
println!(" index bytes: {}", index_bytes);
println!(" hygiene data bytes: {}", hygiene_data_bytes);
println!(" zero bytes: {}", zero_bytes);
println!(" total bytes: {}", total_bytes);
}
Expand Down Expand Up @@ -1678,6 +1717,7 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
predicate_shorthands: Default::default(),
metadata_hashes: EncodedMetadataHashes::new(),
compute_ich,
already_encoded_hygiene_data: false,
};

// Encode the rustc version string in a predictable location.
Expand Down
3 changes: 2 additions & 1 deletion src/librustc_metadata/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use rustc_back::PanicStrategy;
use rustc_serialize as serialize;
use syntax::{ast, attr};
use syntax::symbol::Symbol;
use syntax_pos::{self, Span};
use syntax_pos::{self, hygiene, Span};

use std::marker::PhantomData;
use std::mem;
Expand Down Expand Up @@ -208,6 +208,7 @@ pub struct CrateRoot {
pub impls: LazySeq<TraitImpls>,
pub exported_symbols: LazySeq<DefIndex>,
pub index: LazySeq<index::Index>,
pub hygiene_data: Lazy<hygiene::HygieneDataMap>,
}

#[derive(RustcEncodable, RustcDecodable)]
Expand Down
Loading