From a79104e0c639be1c79bafb338ad7214802caada9 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Sat, 27 Aug 2016 20:18:02 +0300 Subject: [PATCH 01/39] serialize: extend with specialization-based encoding/decoding multi-dispatch. --- src/libserialize/lib.rs | 5 ++ src/libserialize/serialize.rs | 95 +++++++++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+) diff --git a/src/libserialize/lib.rs b/src/libserialize/lib.rs index 80cd47c85ccdf..ebd939120973d 100644 --- a/src/libserialize/lib.rs +++ b/src/libserialize/lib.rs @@ -29,8 +29,10 @@ Core encoding and decoding interfaces. #![feature(box_syntax)] #![feature(collections)] +#![feature(core_intrinsics)] #![feature(enumset)] #![feature(rustc_private)] +#![feature(specialization)] #![feature(staged_api)] #![feature(unicode)] #![feature(question_mark)] @@ -46,6 +48,9 @@ extern crate collections; pub use self::serialize::{Decoder, Encoder, Decodable, Encodable, DecoderHelpers, EncoderHelpers}; +pub use self::serialize::{SpecializationError, SpecializedEncoder, SpecializedDecoder}; +pub use self::serialize::{UseSpecializedEncodable, UseSpecializedDecodable}; + mod serialize; mod collection_impls; diff --git a/src/libserialize/serialize.rs b/src/libserialize/serialize.rs index 8e271597dfcb6..4414fee78788e 100644 --- a/src/libserialize/serialize.rs +++ b/src/libserialize/serialize.rs @@ -14,6 +14,7 @@ Core encoding and decoding interfaces. */ +use std::intrinsics; use std::path; use std::rc::Rc; use std::cell::{Cell, RefCell}; @@ -635,3 +636,97 @@ impl DecoderHelpers for D { }) } } + +// ___________________________________________________________________________ +// Specialization-based interface for multi-dispatch Encodable/Decodable. + +/// Implement this trait on your `{Encodable,Decodable}::Error` types +/// to override the default panic behavior for missing specializations. +pub trait SpecializationError { + /// Create an error for a missing method specialization. + /// Defaults to panicking with type, trait & method names. + /// `S` is the encoder/decoder state type, + /// `T` is the type being encoded/decoded, and + /// the arguments are the names of the trait + /// and method that should've been overriden. + fn not_found(trait_name: &'static str, + method_name: &'static str) -> Self; +} + +impl SpecializationError for E { + default fn not_found(trait_name: &'static str, + method_name: &'static str) -> E { + panic!("missing specializaiton: `<{} as {}<{}>>::{}` not overriden", + unsafe { intrinsics::type_name::() }, + trait_name, + unsafe { intrinsics::type_name::() }, + method_name); + } +} + +/// Implement this trait on encoders, with `T` being the type +/// you want to encode (employing `UseSpecializedEncodable`), +/// using a strategy specific to the encoder. +/// Can also be implemented alongside `UseSpecializedEncodable` +/// to provide a default `specialized_encode` for encoders +/// which do not implement `SpecializedEncoder` themselves. +pub trait SpecializedEncoder: Encoder { + /// Encode the value in a manner specific to this encoder state. + /// Defaults to returning an error (see `SpecializationError`). + fn specialized_encode(&mut self, value: &T) -> Result<(), Self::Error>; +} + +impl SpecializedEncoder for E { + default fn specialized_encode(&mut self, _: &T) -> Result<(), E::Error> { + Err(E::Error::not_found::("SpecializedEncoder", "specialized_encode")) + } +} + +/// Implement this trait on decoders, with `T` being the type +/// you want to decode (employing `UseSpecializedDecodable`), +/// using a strategy specific to the decoder. +/// Can also be implemented alongside `UseSpecializedDecodable` +/// to provide a default `specialized_decode` for decoders +/// which do not implement `SpecializedDecoder` themselves. +pub trait SpecializedDecoder: Decoder { + /// Decode a value in a manner specific to this decoder state. + /// Defaults to returning an error (see `SpecializationError`). + fn specialized_decode(&mut self) -> Result; +} + +impl SpecializedDecoder for D { + default fn specialized_decode(&mut self) -> Result { + Err(D::Error::not_found::("SpecializedDecoder", "specialized_decode")) + } +} + +/// Implement this trait on your type to get an `Encodable` +/// implementation which goes through `SpecializedEncoder`. +pub trait UseSpecializedEncodable {} + +impl Encodable for T { + default fn encode(&self, e: &mut E) -> Result<(), E::Error> { + E::specialized_encode(e, self) + } +} + +/// Implement this trait on your type to get an `Decodable` +/// implementation which goes through `SpecializedDecoder`. +pub trait UseSpecializedDecodable: Sized {} + +impl Decodable for T { + default fn decode(d: &mut D) -> Result { + D::specialized_decode(d) + } +} + +// Can't avoid specialization for &T and Box impls, +// as proxy impls on them are blankets that conflict +// with the Encodable and Decodable impls above, +// which only have `default` on their methods +// for this exact reason. +// May be fixable in a simpler fashion via the +// more complex lattice model for specialization. +impl<'a, T: ?Sized + Encodable> UseSpecializedEncodable for &'a T {} +impl UseSpecializedEncodable for Box {} +impl UseSpecializedDecodable for Box {} From 3ad8aa6b87cb78803d284c37d33a064b5677a5fa Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Sun, 28 Aug 2016 07:10:22 +0300 Subject: [PATCH 02/39] rbml: move the tagged encoder/decoder to librustc_metadata. --- src/librbml/lib.rs | 1550 +------------------------- src/librbml/opaque.rs | 7 +- src/librustc_metadata/lib.rs | 14 +- src/librustc_metadata/rbml/reader.rs | 1025 +++++++++++++++++ src/librustc_metadata/rbml/writer.rs | 522 +++++++++ 5 files changed, 1564 insertions(+), 1554 deletions(-) create mode 100644 src/librustc_metadata/rbml/reader.rs create mode 100644 src/librustc_metadata/rbml/writer.rs diff --git a/src/librbml/lib.rs b/src/librbml/lib.rs index 5a8a52f7dfc6e..65259f903a99c 100644 --- a/src/librbml/lib.rs +++ b/src/librbml/lib.rs @@ -8,108 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Really Bad Markup Language (rbml) is an internal serialization format of rustc. -//! This is not intended to be used by users. -//! -//! Originally based on the Extensible Binary Markup Language -//! (ebml; http://www.matroska.org/technical/specs/rfc/index.html), -//! it is now a separate format tuned for the rust object metadata. -//! -//! # Encoding -//! -//! RBML document consists of the tag, length and data. -//! The encoded data can contain multiple RBML documents concatenated. -//! -//! **Tags** are a hint for the following data. -//! Tags are a number from 0x000 to 0xfff, where 0xf0 through 0xff is reserved. -//! Tags less than 0xf0 are encoded in one literal byte. -//! Tags greater than 0xff are encoded in two big-endian bytes, -//! where the tag number is ORed with 0xf000. (E.g. tag 0x123 = `f1 23`) -//! -//! **Lengths** encode the length of the following data. -//! It is a variable-length unsigned isize, and one of the following forms: -//! -//! - `80` through `fe` for lengths up to 0x7e; -//! - `40 ff` through `7f ff` for lengths up to 0x3fff; -//! - `20 40 00` through `3f ff ff` for lengths up to 0x1fffff; -//! - `10 20 00 00` through `1f ff ff ff` for lengths up to 0xfffffff. -//! -//! The "overlong" form is allowed so that the length can be encoded -//! without the prior knowledge of the encoded data. -//! For example, the length 0 can be represented either by `80`, `40 00`, -//! `20 00 00` or `10 00 00 00`. -//! The encoder tries to minimize the length if possible. -//! Also, some predefined tags listed below are so commonly used that -//! their lengths are omitted ("implicit length"). -//! -//! **Data** can be either binary bytes or zero or more nested RBML documents. -//! Nested documents cannot overflow, and should be entirely contained -//! within a parent document. -//! -//! # Predefined Tags -//! -//! Most RBML tags are defined by the application. -//! (For the rust object metadata, see also `rustc::metadata::common`.) -//! RBML itself does define a set of predefined tags however, -//! intended for the auto-serialization implementation. -//! -//! Predefined tags with an implicit length: -//! -//! - `U8` (`00`): 1-byte unsigned integer. -//! - `U16` (`01`): 2-byte big endian unsigned integer. -//! - `U32` (`02`): 4-byte big endian unsigned integer. -//! - `U64` (`03`): 8-byte big endian unsigned integer. -//! Any of `U*` tags can be used to encode primitive unsigned integer types, -//! as long as it is no greater than the actual size. -//! For example, `u8` can only be represented via the `U8` tag. -//! -//! - `I8` (`04`): 1-byte signed integer. -//! - `I16` (`05`): 2-byte big endian signed integer. -//! - `I32` (`06`): 4-byte big endian signed integer. -//! - `I64` (`07`): 8-byte big endian signed integer. -//! Similar to `U*` tags. Always uses two's complement encoding. -//! -//! - `Bool` (`08`): 1-byte boolean value, `00` for false and `01` for true. -//! -//! - `Char` (`09`): 4-byte big endian Unicode scalar value. -//! Surrogate pairs or out-of-bound values are invalid. -//! -//! - `F32` (`0a`): 4-byte big endian unsigned integer representing -//! IEEE 754 binary32 floating-point format. -//! - `F64` (`0b`): 8-byte big endian unsigned integer representing -//! IEEE 754 binary64 floating-point format. -//! -//! - `Sub8` (`0c`): 1-byte unsigned integer for supplementary information. -//! - `Sub32` (`0d`): 4-byte unsigned integer for supplementary information. -//! Those two tags normally occur as the first subdocument of certain tags, -//! namely `Enum`, `Vec` and `Map`, to provide a variant or size information. -//! They can be used interchangeably. -//! -//! Predefined tags with an explicit length: -//! -//! - `Str` (`10`): A UTF-8-encoded string. -//! -//! - `Enum` (`11`): An enum. -//! The first subdocument should be `Sub*` tags with a variant ID. -//! Subsequent subdocuments, if any, encode variant arguments. -//! -//! - `Vec` (`12`): A vector (sequence). -//! - `VecElt` (`13`): A vector element. -//! The first subdocument should be `Sub*` tags with the number of elements. -//! Subsequent subdocuments should be `VecElt` tag per each element. -//! -//! - `Map` (`14`): A map (associated array). -//! - `MapKey` (`15`): A key part of the map entry. -//! - `MapVal` (`16`): A value part of the map entry. -//! The first subdocument should be `Sub*` tags with the number of entries. -//! Subsequent subdocuments should be an alternating sequence of -//! `MapKey` and `MapVal` tags per each entry. -//! -//! - `Opaque` (`17`): An opaque, custom-format tag. -//! Used to wrap ordinary custom tags or data in the auto-serialized context. -//! Rustc typically uses this to encode type information. -//! -//! First 0x20 tags are reserved by RBML; custom tags start at 0x20. +//! Skeleton of RBML (Really Bad Markup Language). +//! See `src/librustc_metadata/reader.rs` for more details. #![crate_name = "rbml"] #![unstable(feature = "rustc_private", issue = "27812")] @@ -142,93 +42,10 @@ extern crate test; pub mod opaque; pub mod leb128; -pub use self::EbmlEncoderTag::*; pub use self::Error::*; -use std::str; use std::fmt; -/// Common data structures -#[derive(Clone, Copy)] -pub struct Doc<'a> { - pub data: &'a [u8], - pub start: usize, - pub end: usize, -} - -impl<'doc> Doc<'doc> { - pub fn new(data: &'doc [u8]) -> Doc<'doc> { - Doc { - data: data, - start: 0, - end: data.len(), - } - } - - pub fn get(&self, tag: usize) -> Doc<'doc> { - reader::get_doc(*self, tag) - } - - pub fn is_empty(&self) -> bool { - self.start == self.end - } - - pub fn as_str(&self) -> &'doc str { - str::from_utf8(&self.data[self.start..self.end]).unwrap() - } - - pub fn to_string(&self) -> String { - self.as_str().to_string() - } -} - -pub struct TaggedDoc<'a> { - tag: usize, - pub doc: Doc<'a>, -} - -#[derive(Copy, Clone, Debug)] -pub enum EbmlEncoderTag { - // tags 00..1f are reserved for auto-serialization. - // first NUM_IMPLICIT_TAGS tags are implicitly sized and lengths are not encoded. - EsU8 = 0x00, // + 1 byte - EsU16 = 0x01, // + 2 bytes - EsU32 = 0x02, // + 4 bytes - EsU64 = 0x03, // + 8 bytes - EsI8 = 0x04, // + 1 byte - EsI16 = 0x05, // + 2 bytes - EsI32 = 0x06, // + 4 bytes - EsI64 = 0x07, // + 8 bytes - EsBool = 0x08, // + 1 byte - EsChar = 0x09, // + 4 bytes - EsF32 = 0x0a, // + 4 bytes - EsF64 = 0x0b, // + 8 bytes - EsSub8 = 0x0c, // + 1 byte - EsSub32 = 0x0d, // + 4 bytes - // 0x0e and 0x0f are reserved - EsStr = 0x10, - EsEnum = 0x11, // encodes the variant id as the first EsSub* - EsVec = 0x12, // encodes the # of elements as the first EsSub* - EsVecElt = 0x13, - EsMap = 0x14, // encodes the # of pairs as the first EsSub* - EsMapKey = 0x15, - EsMapVal = 0x16, - EsOpaque = 0x17, -} - -const NUM_TAGS: usize = 0x1000; -const NUM_IMPLICIT_TAGS: usize = 0x0e; - -#[cfg_attr(rustfmt, rustfmt_skip)] -static TAG_IMPLICIT_LEN: [i8; NUM_IMPLICIT_TAGS] = [ - 1, 2, 4, 8, // EsU* - 1, 2, 4, 8, // ESI* - 1, // EsBool - 4, // EsChar - 4, 8, // EsF* - 1, 4, // EsSub* -]; - #[derive(Debug)] pub enum Error { IntTooBig(usize), @@ -244,1366 +61,3 @@ impl fmt::Display for Error { fmt::Debug::fmt(self, f) } } -// -------------------------------------- - -pub mod reader { - use std::char; - - use std::isize; - use std::mem::transmute; - - use serialize; - - use super::opaque; - use super::{ApplicationError, EsVec, EsMap, EsEnum, EsSub8, EsSub32, EsVecElt, EsMapKey, - EsU64, EsU32, EsU16, EsU8, EsI64, EsI32, EsI16, EsI8, EsBool, EsF64, EsF32, - EsChar, EsStr, EsMapVal, EsOpaque, EbmlEncoderTag, Doc, TaggedDoc, Error, - IntTooBig, InvalidTag, Expected, NUM_IMPLICIT_TAGS, TAG_IMPLICIT_LEN}; - - pub type DecodeResult = Result; - // rbml reading - - macro_rules! try_or { - ($e:expr, $r:expr) => ( - match $e { - Ok(e) => e, - Err(e) => { - debug!("ignored error: {:?}", e); - return $r - } - } - ) - } - - #[derive(Copy, Clone)] - pub struct Res { - pub val: usize, - pub next: usize, - } - - pub fn tag_at(data: &[u8], start: usize) -> DecodeResult { - let v = data[start] as usize; - if v < 0xf0 { - Ok(Res { - val: v, - next: start + 1, - }) - } else if v > 0xf0 { - Ok(Res { - val: ((v & 0xf) << 8) | data[start + 1] as usize, - next: start + 2, - }) - } else { - // every tag starting with byte 0xf0 is an overlong form, which is prohibited. - Err(InvalidTag(v)) - } - } - - #[inline(never)] - fn vuint_at_slow(data: &[u8], start: usize) -> DecodeResult { - let a = data[start]; - if a & 0x80 != 0 { - return Ok(Res { - val: (a & 0x7f) as usize, - next: start + 1, - }); - } - if a & 0x40 != 0 { - return Ok(Res { - val: ((a & 0x3f) as usize) << 8 | (data[start + 1] as usize), - next: start + 2, - }); - } - if a & 0x20 != 0 { - return Ok(Res { - val: ((a & 0x1f) as usize) << 16 | (data[start + 1] as usize) << 8 | - (data[start + 2] as usize), - next: start + 3, - }); - } - if a & 0x10 != 0 { - return Ok(Res { - val: ((a & 0x0f) as usize) << 24 | (data[start + 1] as usize) << 16 | - (data[start + 2] as usize) << 8 | - (data[start + 3] as usize), - next: start + 4, - }); - } - Err(IntTooBig(a as usize)) - } - - pub fn vuint_at(data: &[u8], start: usize) -> DecodeResult { - if data.len() - start < 4 { - return vuint_at_slow(data, start); - } - - // Lookup table for parsing EBML Element IDs as per - // http://ebml.sourceforge.net/specs/ The Element IDs are parsed by - // reading a big endian u32 positioned at data[start]. Using the four - // most significant bits of the u32 we lookup in the table below how - // the element ID should be derived from it. - // - // The table stores tuples (shift, mask) where shift is the number the - // u32 should be right shifted with and mask is the value the right - // shifted value should be masked with. If for example the most - // significant bit is set this means it's a class A ID and the u32 - // should be right shifted with 24 and masked with 0x7f. Therefore we - // store (24, 0x7f) at index 0x8 - 0xF (four bit numbers where the most - // significant bit is set). - // - // By storing the number of shifts and masks in a table instead of - // checking in order if the most significant bit is set, the second - // most significant bit is set etc. we can replace up to three - // "and+branch" with a single table lookup which gives us a measured - // speedup of around 2x on x86_64. - static SHIFT_MASK_TABLE: [(usize, u32); 16] = [(0, 0x0), - (0, 0x0fffffff), - (8, 0x1fffff), - (8, 0x1fffff), - (16, 0x3fff), - (16, 0x3fff), - (16, 0x3fff), - (16, 0x3fff), - (24, 0x7f), - (24, 0x7f), - (24, 0x7f), - (24, 0x7f), - (24, 0x7f), - (24, 0x7f), - (24, 0x7f), - (24, 0x7f)]; - - unsafe { - let ptr = data.as_ptr().offset(start as isize) as *const u32; - let val = u32::from_be(*ptr); - - let i = (val >> 28) as usize; - let (shift, mask) = SHIFT_MASK_TABLE[i]; - Ok(Res { - val: ((val >> shift) & mask) as usize, - next: start + ((32 - shift) >> 3), - }) - } - } - - pub fn tag_len_at(data: &[u8], tag: Res) -> DecodeResult { - if tag.val < NUM_IMPLICIT_TAGS && TAG_IMPLICIT_LEN[tag.val] >= 0 { - Ok(Res { - val: TAG_IMPLICIT_LEN[tag.val] as usize, - next: tag.next, - }) - } else { - vuint_at(data, tag.next) - } - } - - pub fn doc_at<'a>(data: &'a [u8], start: usize) -> DecodeResult> { - let elt_tag = tag_at(data, start)?; - let elt_size = tag_len_at(data, elt_tag)?; - let end = elt_size.next + elt_size.val; - Ok(TaggedDoc { - tag: elt_tag.val, - doc: Doc { - data: data, - start: elt_size.next, - end: end, - }, - }) - } - - pub fn maybe_get_doc<'a>(d: Doc<'a>, tg: usize) -> Option> { - let mut pos = d.start; - while pos < d.end { - let elt_tag = try_or!(tag_at(d.data, pos), None); - let elt_size = try_or!(tag_len_at(d.data, elt_tag), None); - pos = elt_size.next + elt_size.val; - if elt_tag.val == tg { - return Some(Doc { - data: d.data, - start: elt_size.next, - end: pos, - }); - } - } - None - } - - pub fn get_doc<'a>(d: Doc<'a>, tg: usize) -> Doc<'a> { - match maybe_get_doc(d, tg) { - Some(d) => d, - None => { - error!("failed to find block with tag {:?}", tg); - panic!(); - } - } - } - - pub fn docs<'a>(d: Doc<'a>) -> DocsIterator<'a> { - DocsIterator { d: d } - } - - pub struct DocsIterator<'a> { - d: Doc<'a>, - } - - impl<'a> Iterator for DocsIterator<'a> { - type Item = (usize, Doc<'a>); - - fn next(&mut self) -> Option<(usize, Doc<'a>)> { - if self.d.start >= self.d.end { - return None; - } - - let elt_tag = try_or!(tag_at(self.d.data, self.d.start), { - self.d.start = self.d.end; - None - }); - let elt_size = try_or!(tag_len_at(self.d.data, elt_tag), { - self.d.start = self.d.end; - None - }); - - let end = elt_size.next + elt_size.val; - let doc = Doc { - data: self.d.data, - start: elt_size.next, - end: end, - }; - - self.d.start = end; - return Some((elt_tag.val, doc)); - } - } - - pub fn tagged_docs<'a>(d: Doc<'a>, tag: usize) -> TaggedDocsIterator<'a> { - TaggedDocsIterator { - iter: docs(d), - tag: tag, - } - } - - pub struct TaggedDocsIterator<'a> { - iter: DocsIterator<'a>, - tag: usize, - } - - impl<'a> Iterator for TaggedDocsIterator<'a> { - type Item = Doc<'a>; - - fn next(&mut self) -> Option> { - while let Some((tag, doc)) = self.iter.next() { - if tag == self.tag { - return Some(doc); - } - } - None - } - } - - pub fn with_doc_data(d: Doc, f: F) -> T - where F: FnOnce(&[u8]) -> T - { - f(&d.data[d.start..d.end]) - } - - pub fn doc_as_u8(d: Doc) -> u8 { - assert_eq!(d.end, d.start + 1); - d.data[d.start] - } - - pub fn doc_as_u64(d: Doc) -> u64 { - if d.end >= 8 { - // For performance, we read 8 big-endian bytes, - // and mask off the junk if there is any. This - // obviously won't work on the first 8 bytes - // of a file - we will fall of the start - // of the page and segfault. - - let mut b = [0; 8]; - b.copy_from_slice(&d.data[d.end - 8..d.end]); - let data = unsafe { (*(b.as_ptr() as *const u64)).to_be() }; - let len = d.end - d.start; - if len < 8 { - data & ((1 << (len * 8)) - 1) - } else { - data - } - } else { - let mut result = 0; - for b in &d.data[d.start..d.end] { - result = (result << 8) + (*b as u64); - } - result - } - } - - #[inline] - pub fn doc_as_u16(d: Doc) -> u16 { - doc_as_u64(d) as u16 - } - #[inline] - pub fn doc_as_u32(d: Doc) -> u32 { - doc_as_u64(d) as u32 - } - - #[inline] - pub fn doc_as_i8(d: Doc) -> i8 { - doc_as_u8(d) as i8 - } - #[inline] - pub fn doc_as_i16(d: Doc) -> i16 { - doc_as_u16(d) as i16 - } - #[inline] - pub fn doc_as_i32(d: Doc) -> i32 { - doc_as_u32(d) as i32 - } - #[inline] - pub fn doc_as_i64(d: Doc) -> i64 { - doc_as_u64(d) as i64 - } - - pub struct Decoder<'a> { - parent: Doc<'a>, - pos: usize, - } - - impl<'doc> Decoder<'doc> { - pub fn new(d: Doc<'doc>) -> Decoder<'doc> { - Decoder { - parent: d, - pos: d.start, - } - } - - fn next_doc(&mut self, exp_tag: EbmlEncoderTag) -> DecodeResult> { - debug!(". next_doc(exp_tag={:?})", exp_tag); - if self.pos >= self.parent.end { - return Err(Expected(format!("no more documents in current node!"))); - } - let TaggedDoc { tag: r_tag, doc: r_doc } = doc_at(self.parent.data, self.pos)?; - debug!("self.parent={:?}-{:?} self.pos={:?} r_tag={:?} r_doc={:?}-{:?}", - self.parent.start, - self.parent.end, - self.pos, - r_tag, - r_doc.start, - r_doc.end); - if r_tag != (exp_tag as usize) { - return Err(Expected(format!("expected EBML doc with tag {:?} but found tag {:?}", - exp_tag, - r_tag))); - } - if r_doc.end > self.parent.end { - return Err(Expected(format!("invalid EBML, child extends to {:#x}, parent to \ - {:#x}", - r_doc.end, - self.parent.end))); - } - self.pos = r_doc.end; - Ok(r_doc) - } - - fn push_doc(&mut self, exp_tag: EbmlEncoderTag, f: F) -> DecodeResult - where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult - { - let d = self.next_doc(exp_tag)?; - let old_parent = self.parent; - let old_pos = self.pos; - self.parent = d; - self.pos = d.start; - let r = f(self)?; - self.parent = old_parent; - self.pos = old_pos; - Ok(r) - } - - fn _next_sub(&mut self) -> DecodeResult { - // empty vector/map optimization - if self.parent.is_empty() { - return Ok(0); - } - - let TaggedDoc { tag: r_tag, doc: r_doc } = doc_at(self.parent.data, self.pos)?; - let r = if r_tag == (EsSub8 as usize) { - doc_as_u8(r_doc) as usize - } else if r_tag == (EsSub32 as usize) { - doc_as_u32(r_doc) as usize - } else { - return Err(Expected(format!("expected EBML doc with tag {:?} or {:?} but found \ - tag {:?}", - EsSub8, - EsSub32, - r_tag))); - }; - if r_doc.end > self.parent.end { - return Err(Expected(format!("invalid EBML, child extends to {:#x}, parent to \ - {:#x}", - r_doc.end, - self.parent.end))); - } - self.pos = r_doc.end; - debug!("_next_sub result={:?}", r); - Ok(r) - } - - // variable-length unsigned integer with different tags. - // `first_tag` should be a tag for u8 or i8. - // `last_tag` should be the largest allowed integer tag with the matching signedness. - // all tags between them should be valid, in the order of u8, u16, u32 and u64. - fn _next_int(&mut self, - first_tag: EbmlEncoderTag, - last_tag: EbmlEncoderTag) - -> DecodeResult { - if self.pos >= self.parent.end { - return Err(Expected(format!("no more documents in current node!"))); - } - - let TaggedDoc { tag: r_tag, doc: r_doc } = doc_at(self.parent.data, self.pos)?; - let r = if first_tag as usize <= r_tag && r_tag <= last_tag as usize { - match r_tag - first_tag as usize { - 0 => doc_as_u8(r_doc) as u64, - 1 => doc_as_u16(r_doc) as u64, - 2 => doc_as_u32(r_doc) as u64, - 3 => doc_as_u64(r_doc), - _ => unreachable!(), - } - } else { - return Err(Expected(format!("expected EBML doc with tag {:?} through {:?} but \ - found tag {:?}", - first_tag, - last_tag, - r_tag))); - }; - if r_doc.end > self.parent.end { - return Err(Expected(format!("invalid EBML, child extends to {:#x}, parent to \ - {:#x}", - r_doc.end, - self.parent.end))); - } - self.pos = r_doc.end; - debug!("_next_int({:?}, {:?}) result={:?}", first_tag, last_tag, r); - Ok(r) - } - - pub fn read_opaque(&mut self, op: F) -> DecodeResult - where F: FnOnce(&mut opaque::Decoder, Doc) -> DecodeResult - { - let doc = self.next_doc(EsOpaque)?; - - let result = { - let mut opaque_decoder = opaque::Decoder::new(doc.data, doc.start); - op(&mut opaque_decoder, doc)? - }; - - Ok(result) - } - - pub fn position(&self) -> usize { - self.pos - } - - pub fn advance(&mut self, bytes: usize) { - self.pos += bytes; - } - } - - impl<'doc> serialize::Decoder for Decoder<'doc> { - type Error = Error; - fn read_nil(&mut self) -> DecodeResult<()> { - Ok(()) - } - - fn read_u64(&mut self) -> DecodeResult { - self._next_int(EsU8, EsU64) - } - fn read_u32(&mut self) -> DecodeResult { - Ok(self._next_int(EsU8, EsU32)? as u32) - } - fn read_u16(&mut self) -> DecodeResult { - Ok(self._next_int(EsU8, EsU16)? as u16) - } - fn read_u8(&mut self) -> DecodeResult { - Ok(doc_as_u8(self.next_doc(EsU8)?)) - } - fn read_usize(&mut self) -> DecodeResult { - let v = self._next_int(EsU8, EsU64)?; - if v > (::std::usize::MAX as u64) { - Err(IntTooBig(v as usize)) - } else { - Ok(v as usize) - } - } - - fn read_i64(&mut self) -> DecodeResult { - Ok(self._next_int(EsI8, EsI64)? as i64) - } - fn read_i32(&mut self) -> DecodeResult { - Ok(self._next_int(EsI8, EsI32)? as i32) - } - fn read_i16(&mut self) -> DecodeResult { - Ok(self._next_int(EsI8, EsI16)? as i16) - } - fn read_i8(&mut self) -> DecodeResult { - Ok(doc_as_u8(self.next_doc(EsI8)?) as i8) - } - fn read_isize(&mut self) -> DecodeResult { - let v = self._next_int(EsI8, EsI64)? as i64; - if v > (isize::MAX as i64) || v < (isize::MIN as i64) { - debug!("FIXME \\#6122: Removing this makes this function miscompile"); - Err(IntTooBig(v as usize)) - } else { - Ok(v as isize) - } - } - - fn read_bool(&mut self) -> DecodeResult { - Ok(doc_as_u8(self.next_doc(EsBool)?) != 0) - } - - fn read_f64(&mut self) -> DecodeResult { - let bits = doc_as_u64(self.next_doc(EsF64)?); - Ok(unsafe { transmute(bits) }) - } - fn read_f32(&mut self) -> DecodeResult { - let bits = doc_as_u32(self.next_doc(EsF32)?); - Ok(unsafe { transmute(bits) }) - } - fn read_char(&mut self) -> DecodeResult { - Ok(char::from_u32(doc_as_u32(self.next_doc(EsChar)?)).unwrap()) - } - fn read_str(&mut self) -> DecodeResult { - Ok(self.next_doc(EsStr)?.to_string()) - } - - // Compound types: - fn read_enum(&mut self, name: &str, f: F) -> DecodeResult - where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult - { - debug!("read_enum({})", name); - - let doc = self.next_doc(EsEnum)?; - - let (old_parent, old_pos) = (self.parent, self.pos); - self.parent = doc; - self.pos = self.parent.start; - - let result = f(self)?; - - self.parent = old_parent; - self.pos = old_pos; - Ok(result) - } - - fn read_enum_variant(&mut self, _: &[&str], mut f: F) -> DecodeResult - where F: FnMut(&mut Decoder<'doc>, usize) -> DecodeResult - { - debug!("read_enum_variant()"); - let idx = self._next_sub()?; - debug!(" idx={}", idx); - - f(self, idx) - } - - fn read_enum_variant_arg(&mut self, idx: usize, f: F) -> DecodeResult - where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult - { - debug!("read_enum_variant_arg(idx={})", idx); - f(self) - } - - fn read_enum_struct_variant(&mut self, _: &[&str], mut f: F) -> DecodeResult - where F: FnMut(&mut Decoder<'doc>, usize) -> DecodeResult - { - debug!("read_enum_struct_variant()"); - let idx = self._next_sub()?; - debug!(" idx={}", idx); - - f(self, idx) - } - - fn read_enum_struct_variant_field(&mut self, - name: &str, - idx: usize, - f: F) - -> DecodeResult - where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult - { - debug!("read_enum_struct_variant_arg(name={}, idx={})", name, idx); - f(self) - } - - fn read_struct(&mut self, name: &str, _: usize, f: F) -> DecodeResult - where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult - { - debug!("read_struct(name={})", name); - f(self) - } - - fn read_struct_field(&mut self, name: &str, idx: usize, f: F) -> DecodeResult - where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult - { - debug!("read_struct_field(name={}, idx={})", name, idx); - f(self) - } - - fn read_tuple(&mut self, tuple_len: usize, f: F) -> DecodeResult - where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult - { - debug!("read_tuple()"); - self.read_seq(move |d, len| { - if len == tuple_len { - f(d) - } else { - Err(Expected(format!("Expected tuple of length `{}`, found tuple of length \ - `{}`", - tuple_len, - len))) - } - }) - } - - fn read_tuple_arg(&mut self, idx: usize, f: F) -> DecodeResult - where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult - { - debug!("read_tuple_arg(idx={})", idx); - self.read_seq_elt(idx, f) - } - - fn read_tuple_struct(&mut self, name: &str, len: usize, f: F) -> DecodeResult - where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult - { - debug!("read_tuple_struct(name={})", name); - self.read_tuple(len, f) - } - - fn read_tuple_struct_arg(&mut self, idx: usize, f: F) -> DecodeResult - where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult - { - debug!("read_tuple_struct_arg(idx={})", idx); - self.read_tuple_arg(idx, f) - } - - fn read_option(&mut self, mut f: F) -> DecodeResult - where F: FnMut(&mut Decoder<'doc>, bool) -> DecodeResult - { - debug!("read_option()"); - self.read_enum("Option", move |this| { - this.read_enum_variant(&["None", "Some"], move |this, idx| { - match idx { - 0 => f(this, false), - 1 => f(this, true), - _ => Err(Expected(format!("Expected None or Some"))), - } - }) - }) - } - - fn read_seq(&mut self, f: F) -> DecodeResult - where F: FnOnce(&mut Decoder<'doc>, usize) -> DecodeResult - { - debug!("read_seq()"); - self.push_doc(EsVec, move |d| { - let len = d._next_sub()?; - debug!(" len={}", len); - f(d, len) - }) - } - - fn read_seq_elt(&mut self, idx: usize, f: F) -> DecodeResult - where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult - { - debug!("read_seq_elt(idx={})", idx); - self.push_doc(EsVecElt, f) - } - - fn read_map(&mut self, f: F) -> DecodeResult - where F: FnOnce(&mut Decoder<'doc>, usize) -> DecodeResult - { - debug!("read_map()"); - self.push_doc(EsMap, move |d| { - let len = d._next_sub()?; - debug!(" len={}", len); - f(d, len) - }) - } - - fn read_map_elt_key(&mut self, idx: usize, f: F) -> DecodeResult - where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult - { - debug!("read_map_elt_key(idx={})", idx); - self.push_doc(EsMapKey, f) - } - - fn read_map_elt_val(&mut self, idx: usize, f: F) -> DecodeResult - where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult - { - debug!("read_map_elt_val(idx={})", idx); - self.push_doc(EsMapVal, f) - } - - fn error(&mut self, err: &str) -> Error { - ApplicationError(err.to_string()) - } - } -} - -pub mod writer { - use std::mem; - use std::io::prelude::*; - use std::io::{self, SeekFrom, Cursor}; - - use super::opaque; - use super::{EsVec, EsMap, EsEnum, EsSub8, EsSub32, EsVecElt, EsMapKey, EsU64, EsU32, EsU16, - EsU8, EsI64, EsI32, EsI16, EsI8, EsBool, EsF64, EsF32, EsChar, EsStr, EsMapVal, - EsOpaque, NUM_IMPLICIT_TAGS, NUM_TAGS}; - - use serialize; - - - pub type EncodeResult = io::Result<()>; - - // rbml writing - pub struct Encoder<'a> { - pub writer: &'a mut Cursor>, - size_positions: Vec, - relax_limit: u64, // do not move encoded bytes before this position - } - - fn write_tag(w: &mut W, n: usize) -> EncodeResult { - if n < 0xf0 { - w.write_all(&[n as u8]) - } else if 0x100 <= n && n < NUM_TAGS { - w.write_all(&[0xf0 | (n >> 8) as u8, n as u8]) - } else { - Err(io::Error::new(io::ErrorKind::Other, &format!("invalid tag: {}", n)[..])) - } - } - - fn write_sized_vuint(w: &mut W, n: usize, size: usize) -> EncodeResult { - match size { - 1 => w.write_all(&[0x80 | (n as u8)]), - 2 => w.write_all(&[0x40 | ((n >> 8) as u8), n as u8]), - 3 => w.write_all(&[0x20 | ((n >> 16) as u8), (n >> 8) as u8, n as u8]), - 4 => w.write_all(&[0x10 | ((n >> 24) as u8), (n >> 16) as u8, (n >> 8) as u8, n as u8]), - _ => Err(io::Error::new(io::ErrorKind::Other, &format!("isize too big: {}", n)[..])), - } - } - - pub fn write_vuint(w: &mut W, n: usize) -> EncodeResult { - if n < 0x7f { - return write_sized_vuint(w, n, 1); - } - if n < 0x4000 { - return write_sized_vuint(w, n, 2); - } - if n < 0x200000 { - return write_sized_vuint(w, n, 3); - } - if n < 0x10000000 { - return write_sized_vuint(w, n, 4); - } - Err(io::Error::new(io::ErrorKind::Other, &format!("isize too big: {}", n)[..])) - } - - impl<'a> Encoder<'a> { - pub fn new(w: &'a mut Cursor>) -> Encoder<'a> { - Encoder { - writer: w, - size_positions: vec![], - relax_limit: 0, - } - } - - pub fn start_tag(&mut self, tag_id: usize) -> EncodeResult { - debug!("Start tag {:?}", tag_id); - assert!(tag_id >= NUM_IMPLICIT_TAGS); - - // Write the enum ID: - write_tag(self.writer, tag_id)?; - - // Write a placeholder four-byte size. - let cur_pos = self.writer.seek(SeekFrom::Current(0))?; - self.size_positions.push(cur_pos); - let zeroes: &[u8] = &[0, 0, 0, 0]; - self.writer.write_all(zeroes) - } - - pub fn end_tag(&mut self) -> EncodeResult { - let last_size_pos = self.size_positions.pop().unwrap(); - let cur_pos = self.writer.seek(SeekFrom::Current(0))?; - self.writer.seek(SeekFrom::Start(last_size_pos))?; - let size = (cur_pos - last_size_pos - 4) as usize; - - // relax the size encoding for small tags (bigger tags are costly to move). - // we should never try to move the stable positions, however. - const RELAX_MAX_SIZE: usize = 0x100; - if size <= RELAX_MAX_SIZE && last_size_pos >= self.relax_limit { - // we can't alter the buffer in place, so have a temporary buffer - let mut buf = [0u8; RELAX_MAX_SIZE]; - { - let last_size_pos = last_size_pos as usize; - let data = &self.writer.get_ref()[last_size_pos + 4..cur_pos as usize]; - buf[..size].copy_from_slice(data); - } - - // overwrite the size and data and continue - write_vuint(self.writer, size)?; - self.writer.write_all(&buf[..size])?; - } else { - // overwrite the size with an overlong encoding and skip past the data - write_sized_vuint(self.writer, size, 4)?; - self.writer.seek(SeekFrom::Start(cur_pos))?; - } - - debug!("End tag (size = {:?})", size); - Ok(()) - } - - pub fn wr_tag(&mut self, tag_id: usize, blk: F) -> EncodeResult - where F: FnOnce() -> EncodeResult - { - self.start_tag(tag_id)?; - blk()?; - self.end_tag() - } - - pub fn wr_tagged_bytes(&mut self, tag_id: usize, b: &[u8]) -> EncodeResult { - assert!(tag_id >= NUM_IMPLICIT_TAGS); - write_tag(self.writer, tag_id)?; - write_vuint(self.writer, b.len())?; - self.writer.write_all(b) - } - - pub fn wr_tagged_u64(&mut self, tag_id: usize, v: u64) -> EncodeResult { - let bytes: [u8; 8] = unsafe { mem::transmute(v.to_be()) }; - // tagged integers are emitted in big-endian, with no - // leading zeros. - let leading_zero_bytes = v.leading_zeros() / 8; - self.wr_tagged_bytes(tag_id, &bytes[leading_zero_bytes as usize..]) - } - - #[inline] - pub fn wr_tagged_u32(&mut self, tag_id: usize, v: u32) -> EncodeResult { - self.wr_tagged_u64(tag_id, v as u64) - } - - #[inline] - pub fn wr_tagged_u16(&mut self, tag_id: usize, v: u16) -> EncodeResult { - self.wr_tagged_u64(tag_id, v as u64) - } - - #[inline] - pub fn wr_tagged_u8(&mut self, tag_id: usize, v: u8) -> EncodeResult { - self.wr_tagged_bytes(tag_id, &[v]) - } - - #[inline] - pub fn wr_tagged_i64(&mut self, tag_id: usize, v: i64) -> EncodeResult { - self.wr_tagged_u64(tag_id, v as u64) - } - - #[inline] - pub fn wr_tagged_i32(&mut self, tag_id: usize, v: i32) -> EncodeResult { - self.wr_tagged_u32(tag_id, v as u32) - } - - #[inline] - pub fn wr_tagged_i16(&mut self, tag_id: usize, v: i16) -> EncodeResult { - self.wr_tagged_u16(tag_id, v as u16) - } - - #[inline] - pub fn wr_tagged_i8(&mut self, tag_id: usize, v: i8) -> EncodeResult { - self.wr_tagged_bytes(tag_id, &[v as u8]) - } - - pub fn wr_tagged_str(&mut self, tag_id: usize, v: &str) -> EncodeResult { - self.wr_tagged_bytes(tag_id, v.as_bytes()) - } - - // for auto-serialization - fn wr_tagged_raw_bytes(&mut self, tag_id: usize, b: &[u8]) -> EncodeResult { - write_tag(self.writer, tag_id)?; - self.writer.write_all(b) - } - - fn wr_tagged_raw_u64(&mut self, tag_id: usize, v: u64) -> EncodeResult { - let bytes: [u8; 8] = unsafe { mem::transmute(v.to_be()) }; - self.wr_tagged_raw_bytes(tag_id, &bytes) - } - - fn wr_tagged_raw_u32(&mut self, tag_id: usize, v: u32) -> EncodeResult { - let bytes: [u8; 4] = unsafe { mem::transmute(v.to_be()) }; - self.wr_tagged_raw_bytes(tag_id, &bytes) - } - - fn wr_tagged_raw_u16(&mut self, tag_id: usize, v: u16) -> EncodeResult { - let bytes: [u8; 2] = unsafe { mem::transmute(v.to_be()) }; - self.wr_tagged_raw_bytes(tag_id, &bytes) - } - - fn wr_tagged_raw_u8(&mut self, tag_id: usize, v: u8) -> EncodeResult { - self.wr_tagged_raw_bytes(tag_id, &[v]) - } - - fn wr_tagged_raw_i64(&mut self, tag_id: usize, v: i64) -> EncodeResult { - self.wr_tagged_raw_u64(tag_id, v as u64) - } - - fn wr_tagged_raw_i32(&mut self, tag_id: usize, v: i32) -> EncodeResult { - self.wr_tagged_raw_u32(tag_id, v as u32) - } - - fn wr_tagged_raw_i16(&mut self, tag_id: usize, v: i16) -> EncodeResult { - self.wr_tagged_raw_u16(tag_id, v as u16) - } - - fn wr_tagged_raw_i8(&mut self, tag_id: usize, v: i8) -> EncodeResult { - self.wr_tagged_raw_bytes(tag_id, &[v as u8]) - } - - pub fn wr_bytes(&mut self, b: &[u8]) -> EncodeResult { - debug!("Write {:?} bytes", b.len()); - self.writer.write_all(b) - } - - pub fn wr_str(&mut self, s: &str) -> EncodeResult { - debug!("Write str: {:?}", s); - self.writer.write_all(s.as_bytes()) - } - - /// Returns the current position while marking it stable, i.e. - /// generated bytes so far wouldn't be affected by relaxation. - pub fn mark_stable_position(&mut self) -> u64 { - let pos = self.writer.seek(SeekFrom::Current(0)).unwrap(); - if self.relax_limit < pos { - self.relax_limit = pos; - } - pos - } - } - - impl<'a> Encoder<'a> { - // used internally to emit things like the vector length and so on - fn _emit_tagged_sub(&mut self, v: usize) -> EncodeResult { - if v as u8 as usize == v { - self.wr_tagged_raw_u8(EsSub8 as usize, v as u8) - } else if v as u32 as usize == v { - self.wr_tagged_raw_u32(EsSub32 as usize, v as u32) - } else { - Err(io::Error::new(io::ErrorKind::Other, - &format!("length or variant id too big: {}", v)[..])) - } - } - - pub fn emit_opaque(&mut self, f: F) -> EncodeResult - where F: FnOnce(&mut opaque::Encoder) -> EncodeResult - { - self.start_tag(EsOpaque as usize)?; - - { - let mut opaque_encoder = opaque::Encoder::new(self.writer); - f(&mut opaque_encoder)?; - } - - self.mark_stable_position(); - self.end_tag() - } - } - - impl<'a> serialize::Encoder for Encoder<'a> { - type Error = io::Error; - - fn emit_nil(&mut self) -> EncodeResult { - Ok(()) - } - - fn emit_usize(&mut self, v: usize) -> EncodeResult { - self.emit_u64(v as u64) - } - fn emit_u64(&mut self, v: u64) -> EncodeResult { - if v as u32 as u64 == v { - self.emit_u32(v as u32) - } else { - self.wr_tagged_raw_u64(EsU64 as usize, v) - } - } - fn emit_u32(&mut self, v: u32) -> EncodeResult { - if v as u16 as u32 == v { - self.emit_u16(v as u16) - } else { - self.wr_tagged_raw_u32(EsU32 as usize, v) - } - } - fn emit_u16(&mut self, v: u16) -> EncodeResult { - if v as u8 as u16 == v { - self.emit_u8(v as u8) - } else { - self.wr_tagged_raw_u16(EsU16 as usize, v) - } - } - fn emit_u8(&mut self, v: u8) -> EncodeResult { - self.wr_tagged_raw_u8(EsU8 as usize, v) - } - - fn emit_isize(&mut self, v: isize) -> EncodeResult { - self.emit_i64(v as i64) - } - fn emit_i64(&mut self, v: i64) -> EncodeResult { - if v as i32 as i64 == v { - self.emit_i32(v as i32) - } else { - self.wr_tagged_raw_i64(EsI64 as usize, v) - } - } - fn emit_i32(&mut self, v: i32) -> EncodeResult { - if v as i16 as i32 == v { - self.emit_i16(v as i16) - } else { - self.wr_tagged_raw_i32(EsI32 as usize, v) - } - } - fn emit_i16(&mut self, v: i16) -> EncodeResult { - if v as i8 as i16 == v { - self.emit_i8(v as i8) - } else { - self.wr_tagged_raw_i16(EsI16 as usize, v) - } - } - fn emit_i8(&mut self, v: i8) -> EncodeResult { - self.wr_tagged_raw_i8(EsI8 as usize, v) - } - - fn emit_bool(&mut self, v: bool) -> EncodeResult { - self.wr_tagged_raw_u8(EsBool as usize, v as u8) - } - - fn emit_f64(&mut self, v: f64) -> EncodeResult { - let bits = unsafe { mem::transmute(v) }; - self.wr_tagged_raw_u64(EsF64 as usize, bits) - } - fn emit_f32(&mut self, v: f32) -> EncodeResult { - let bits = unsafe { mem::transmute(v) }; - self.wr_tagged_raw_u32(EsF32 as usize, bits) - } - fn emit_char(&mut self, v: char) -> EncodeResult { - self.wr_tagged_raw_u32(EsChar as usize, v as u32) - } - - fn emit_str(&mut self, v: &str) -> EncodeResult { - self.wr_tagged_str(EsStr as usize, v) - } - - fn emit_enum(&mut self, _name: &str, f: F) -> EncodeResult - where F: FnOnce(&mut Encoder<'a>) -> EncodeResult - { - self.start_tag(EsEnum as usize)?; - f(self)?; - self.end_tag() - } - - fn emit_enum_variant(&mut self, _: &str, v_id: usize, _: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Encoder<'a>) -> EncodeResult - { - self._emit_tagged_sub(v_id)?; - f(self) - } - - fn emit_enum_variant_arg(&mut self, _: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Encoder<'a>) -> EncodeResult - { - f(self) - } - - fn emit_enum_struct_variant(&mut self, - v_name: &str, - v_id: usize, - cnt: usize, - f: F) - -> EncodeResult - where F: FnOnce(&mut Encoder<'a>) -> EncodeResult - { - self.emit_enum_variant(v_name, v_id, cnt, f) - } - - fn emit_enum_struct_variant_field(&mut self, _: &str, idx: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Encoder<'a>) -> EncodeResult - { - self.emit_enum_variant_arg(idx, f) - } - - fn emit_struct(&mut self, _: &str, _len: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Encoder<'a>) -> EncodeResult - { - f(self) - } - - fn emit_struct_field(&mut self, _name: &str, _: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Encoder<'a>) -> EncodeResult - { - f(self) - } - - fn emit_tuple(&mut self, len: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Encoder<'a>) -> EncodeResult - { - self.emit_seq(len, f) - } - fn emit_tuple_arg(&mut self, idx: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Encoder<'a>) -> EncodeResult - { - self.emit_seq_elt(idx, f) - } - - fn emit_tuple_struct(&mut self, _: &str, len: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Encoder<'a>) -> EncodeResult - { - self.emit_seq(len, f) - } - fn emit_tuple_struct_arg(&mut self, idx: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Encoder<'a>) -> EncodeResult - { - self.emit_seq_elt(idx, f) - } - - fn emit_option(&mut self, f: F) -> EncodeResult - where F: FnOnce(&mut Encoder<'a>) -> EncodeResult - { - self.emit_enum("Option", f) - } - fn emit_option_none(&mut self) -> EncodeResult { - self.emit_enum_variant("None", 0, 0, |_| Ok(())) - } - fn emit_option_some(&mut self, f: F) -> EncodeResult - where F: FnOnce(&mut Encoder<'a>) -> EncodeResult - { - - self.emit_enum_variant("Some", 1, 1, f) - } - - fn emit_seq(&mut self, len: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Encoder<'a>) -> EncodeResult - { - if len == 0 { - // empty vector optimization - return self.wr_tagged_bytes(EsVec as usize, &[]); - } - - self.start_tag(EsVec as usize)?; - self._emit_tagged_sub(len)?; - f(self)?; - self.end_tag() - } - - fn emit_seq_elt(&mut self, _idx: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Encoder<'a>) -> EncodeResult - { - - self.start_tag(EsVecElt as usize)?; - f(self)?; - self.end_tag() - } - - fn emit_map(&mut self, len: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Encoder<'a>) -> EncodeResult - { - if len == 0 { - // empty map optimization - return self.wr_tagged_bytes(EsMap as usize, &[]); - } - - self.start_tag(EsMap as usize)?; - self._emit_tagged_sub(len)?; - f(self)?; - self.end_tag() - } - - fn emit_map_elt_key(&mut self, _idx: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Encoder<'a>) -> EncodeResult - { - - self.start_tag(EsMapKey as usize)?; - f(self)?; - self.end_tag() - } - - fn emit_map_elt_val(&mut self, _idx: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Encoder<'a>) -> EncodeResult - { - self.start_tag(EsMapVal as usize)?; - f(self)?; - self.end_tag() - } - } -} - -// ___________________________________________________________________________ -// Testing - -#[cfg(test)] -mod tests { - use super::{Doc, reader, writer}; - - use serialize::{Encodable, Decodable}; - - use std::io::Cursor; - - #[test] - fn test_vuint_at() { - let data = &[ - 0x80, - 0xff, - 0x40, 0x00, - 0x7f, 0xff, - 0x20, 0x00, 0x00, - 0x3f, 0xff, 0xff, - 0x10, 0x00, 0x00, 0x00, - 0x1f, 0xff, 0xff, 0xff - ]; - - let mut res: reader::Res; - - // Class A - res = reader::vuint_at(data, 0).unwrap(); - assert_eq!(res.val, 0); - assert_eq!(res.next, 1); - res = reader::vuint_at(data, res.next).unwrap(); - assert_eq!(res.val, (1 << 7) - 1); - assert_eq!(res.next, 2); - - // Class B - res = reader::vuint_at(data, res.next).unwrap(); - assert_eq!(res.val, 0); - assert_eq!(res.next, 4); - res = reader::vuint_at(data, res.next).unwrap(); - assert_eq!(res.val, (1 << 14) - 1); - assert_eq!(res.next, 6); - - // Class C - res = reader::vuint_at(data, res.next).unwrap(); - assert_eq!(res.val, 0); - assert_eq!(res.next, 9); - res = reader::vuint_at(data, res.next).unwrap(); - assert_eq!(res.val, (1 << 21) - 1); - assert_eq!(res.next, 12); - - // Class D - res = reader::vuint_at(data, res.next).unwrap(); - assert_eq!(res.val, 0); - assert_eq!(res.next, 16); - res = reader::vuint_at(data, res.next).unwrap(); - assert_eq!(res.val, (1 << 28) - 1); - assert_eq!(res.next, 20); - } - - #[test] - fn test_option_int() { - fn test_v(v: Option) { - debug!("v == {:?}", v); - let mut wr = Cursor::new(Vec::new()); - { - let mut rbml_w = writer::Encoder::new(&mut wr); - let _ = v.encode(&mut rbml_w); - } - let rbml_doc = Doc::new(wr.get_ref()); - let mut deser = reader::Decoder::new(rbml_doc); - let v1 = Decodable::decode(&mut deser).unwrap(); - debug!("v1 == {:?}", v1); - assert_eq!(v, v1); - } - - test_v(Some(22)); - test_v(None); - test_v(Some(3)); - } -} - -#[cfg(test)] -mod bench { - #![allow(non_snake_case)] - use test::Bencher; - use super::reader; - - #[bench] - pub fn vuint_at_A_aligned(b: &mut Bencher) { - let data = (0..4 * 100) - .map(|i| { - match i % 2 { - 0 => 0x80, - _ => i as u8, - } - }) - .collect::>(); - let mut sum = 0; - b.iter(|| { - let mut i = 0; - while i < data.len() { - sum += reader::vuint_at(&data, i).unwrap().val; - i += 4; - } - }); - } - - #[bench] - pub fn vuint_at_A_unaligned(b: &mut Bencher) { - let data = (0..4 * 100 + 1) - .map(|i| { - match i % 2 { - 1 => 0x80, - _ => i as u8, - } - }) - .collect::>(); - let mut sum = 0; - b.iter(|| { - let mut i = 1; - while i < data.len() { - sum += reader::vuint_at(&data, i).unwrap().val; - i += 4; - } - }); - } - - #[bench] - pub fn vuint_at_D_aligned(b: &mut Bencher) { - let data = (0..4 * 100) - .map(|i| { - match i % 4 { - 0 => 0x10, - 3 => i as u8, - _ => 0, - } - }) - .collect::>(); - let mut sum = 0; - b.iter(|| { - let mut i = 0; - while i < data.len() { - sum += reader::vuint_at(&data, i).unwrap().val; - i += 4; - } - }); - } - - #[bench] - pub fn vuint_at_D_unaligned(b: &mut Bencher) { - let data = (0..4 * 100 + 1) - .map(|i| { - match i % 4 { - 1 => 0x10, - 0 => i as u8, - _ => 0, - } - }) - .collect::>(); - let mut sum = 0; - b.iter(|| { - let mut i = 1; - while i < data.len() { - sum += reader::vuint_at(&data, i).unwrap().val; - i += 4; - } - }); - } -} diff --git a/src/librbml/opaque.rs b/src/librbml/opaque.rs index 6dc7a72b1b1bb..55ab2afe4454d 100644 --- a/src/librbml/opaque.rs +++ b/src/librbml/opaque.rs @@ -9,7 +9,6 @@ // except according to those terms. use Error as DecodeError; -use writer::EncodeResult; use leb128::{read_signed_leb128, read_unsigned_leb128, write_signed_leb128, write_unsigned_leb128}; use std::io::{self, Write}; use serialize; @@ -18,6 +17,8 @@ use serialize; // Encoder // ----------------------------------------------------------------------------- +pub type EncodeResult = io::Result<()>; + pub struct Encoder<'a> { pub cursor: &'a mut io::Cursor>, } @@ -255,10 +256,6 @@ impl<'a> Encoder<'a> { pub fn position(&self) -> usize { self.cursor.position() as usize } - - pub fn from_rbml<'b: 'c, 'c>(rbml: &'c mut ::writer::Encoder<'b>) -> Encoder<'c> { - Encoder { cursor: rbml.writer } - } } // ----------------------------------------------------------------------------- diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs index 9fb6193400982..d0d3d822f8605 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -27,13 +27,13 @@ #![feature(rustc_macro_internals)] #![feature(rustc_private)] #![feature(staged_api)] +#![cfg_attr(test, feature(test))] #[macro_use] extern crate log; #[macro_use] extern crate syntax; #[macro_use] #[no_link] extern crate rustc_bitflags; extern crate syntax_pos; extern crate flate; -extern crate rbml; extern crate serialize as rustc_serialize; // used by deriving extern crate rustc_errors as errors; extern crate syntax_ext; @@ -46,6 +46,18 @@ extern crate rustc_llvm; extern crate rustc_macro; extern crate rustc_const_math; +#[cfg(test)] +extern crate test; + +pub mod rbml { + pub extern crate rbml as rbml_crate; + pub use self::rbml_crate::{Error, leb128, opaque}; + + pub mod writer; + pub mod reader; + pub use self::reader::Doc; +} + pub use rustc::middle; #[macro_use] diff --git a/src/librustc_metadata/rbml/reader.rs b/src/librustc_metadata/rbml/reader.rs new file mode 100644 index 0000000000000..0950372477e46 --- /dev/null +++ b/src/librustc_metadata/rbml/reader.rs @@ -0,0 +1,1025 @@ +// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Really Bad Markup Language (rbml) is an internal serialization format of rustc. +//! This is not intended to be used by users. +//! +//! Originally based on the Extensible Binary Markup Language +//! (ebml; http://www.matroska.org/technical/specs/rfc/index.html), +//! it is now a separate format tuned for the rust object metadata. +//! +//! # Encoding +//! +//! RBML document consists of the tag, length and data. +//! The encoded data can contain multiple RBML documents concatenated. +//! +//! **Tags** are a hint for the following data. +//! Tags are a number from 0x000 to 0xfff, where 0xf0 through 0xff is reserved. +//! Tags less than 0xf0 are encoded in one literal byte. +//! Tags greater than 0xff are encoded in two big-endian bytes, +//! where the tag number is ORed with 0xf000. (E.g. tag 0x123 = `f1 23`) +//! +//! **Lengths** encode the length of the following data. +//! It is a variable-length unsigned isize, and one of the following forms: +//! +//! - `80` through `fe` for lengths up to 0x7e; +//! - `40 ff` through `7f ff` for lengths up to 0x3fff; +//! - `20 40 00` through `3f ff ff` for lengths up to 0x1fffff; +//! - `10 20 00 00` through `1f ff ff ff` for lengths up to 0xfffffff. +//! +//! The "overlong" form is allowed so that the length can be encoded +//! without the prior knowledge of the encoded data. +//! For example, the length 0 can be represented either by `80`, `40 00`, +//! `20 00 00` or `10 00 00 00`. +//! The encoder tries to minimize the length if possible. +//! Also, some predefined tags listed below are so commonly used that +//! their lengths are omitted ("implicit length"). +//! +//! **Data** can be either binary bytes or zero or more nested RBML documents. +//! Nested documents cannot overflow, and should be entirely contained +//! within a parent document. +//! +//! # Predefined Tags +//! +//! Most RBML tags are defined by the application. +//! (For the rust object metadata, see also `rustc::metadata::common`.) +//! RBML itself does define a set of predefined tags however, +//! intended for the auto-serialization implementation. +//! +//! Predefined tags with an implicit length: +//! +//! - `U8` (`00`): 1-byte unsigned integer. +//! - `U16` (`01`): 2-byte big endian unsigned integer. +//! - `U32` (`02`): 4-byte big endian unsigned integer. +//! - `U64` (`03`): 8-byte big endian unsigned integer. +//! Any of `U*` tags can be used to encode primitive unsigned integer types, +//! as long as it is no greater than the actual size. +//! For example, `u8` can only be represented via the `U8` tag. +//! +//! - `I8` (`04`): 1-byte signed integer. +//! - `I16` (`05`): 2-byte big endian signed integer. +//! - `I32` (`06`): 4-byte big endian signed integer. +//! - `I64` (`07`): 8-byte big endian signed integer. +//! Similar to `U*` tags. Always uses two's complement encoding. +//! +//! - `Bool` (`08`): 1-byte boolean value, `00` for false and `01` for true. +//! +//! - `Char` (`09`): 4-byte big endian Unicode scalar value. +//! Surrogate pairs or out-of-bound values are invalid. +//! +//! - `F32` (`0a`): 4-byte big endian unsigned integer representing +//! IEEE 754 binary32 floating-point format. +//! - `F64` (`0b`): 8-byte big endian unsigned integer representing +//! IEEE 754 binary64 floating-point format. +//! +//! - `Sub8` (`0c`): 1-byte unsigned integer for supplementary information. +//! - `Sub32` (`0d`): 4-byte unsigned integer for supplementary information. +//! Those two tags normally occur as the first subdocument of certain tags, +//! namely `Enum`, `Vec` and `Map`, to provide a variant or size information. +//! They can be used interchangeably. +//! +//! Predefined tags with an explicit length: +//! +//! - `Str` (`10`): A UTF-8-encoded string. +//! +//! - `Enum` (`11`): An enum. +//! The first subdocument should be `Sub*` tags with a variant ID. +//! Subsequent subdocuments, if any, encode variant arguments. +//! +//! - `Vec` (`12`): A vector (sequence). +//! - `VecElt` (`13`): A vector element. +//! The first subdocument should be `Sub*` tags with the number of elements. +//! Subsequent subdocuments should be `VecElt` tag per each element. +//! +//! - `Map` (`14`): A map (associated array). +//! - `MapKey` (`15`): A key part of the map entry. +//! - `MapVal` (`16`): A value part of the map entry. +//! The first subdocument should be `Sub*` tags with the number of entries. +//! Subsequent subdocuments should be an alternating sequence of +//! `MapKey` and `MapVal` tags per each entry. +//! +//! - `Opaque` (`17`): An opaque, custom-format tag. +//! Used to wrap ordinary custom tags or data in the auto-serialized context. +//! Rustc typically uses this to encode type information. +//! +//! First 0x20 tags are reserved by RBML; custom tags start at 0x20. + +#[cfg(test)] +use test::Bencher; + +pub use self::EbmlEncoderTag::*; + +use std::char; +use std::isize; +use std::mem::transmute; +use std::str; + +use rustc_serialize as serialize; + +use rbml::opaque; +use rbml::Error; +use rbml::Error::*; + +#[derive(Clone, Copy)] +pub struct Doc<'a> { + pub data: &'a [u8], + pub start: usize, + pub end: usize, +} + +impl<'doc> Doc<'doc> { + pub fn new(data: &'doc [u8]) -> Doc<'doc> { + Doc { + data: data, + start: 0, + end: data.len(), + } + } + + pub fn get(&self, tag: usize) -> Doc<'doc> { + get_doc(*self, tag) + } + + pub fn is_empty(&self) -> bool { + self.start == self.end + } + + pub fn as_str(&self) -> &'doc str { + str::from_utf8(&self.data[self.start..self.end]).unwrap() + } + + pub fn to_string(&self) -> String { + self.as_str().to_string() + } +} + +pub struct TaggedDoc<'a> { + tag: usize, + pub doc: Doc<'a>, +} + +pub type DecodeResult = Result; + +#[derive(Copy, Clone, Debug)] +pub enum EbmlEncoderTag { + // tags 00..1f are reserved for auto-serialization. + // first NUM_IMPLICIT_TAGS tags are implicitly sized and lengths are not encoded. + EsU8 = 0x00, // + 1 byte + EsU16 = 0x01, // + 2 bytes + EsU32 = 0x02, // + 4 bytes + EsU64 = 0x03, // + 8 bytes + EsI8 = 0x04, // + 1 byte + EsI16 = 0x05, // + 2 bytes + EsI32 = 0x06, // + 4 bytes + EsI64 = 0x07, // + 8 bytes + EsBool = 0x08, // + 1 byte + EsChar = 0x09, // + 4 bytes + EsF32 = 0x0a, // + 4 bytes + EsF64 = 0x0b, // + 8 bytes + EsSub8 = 0x0c, // + 1 byte + EsSub32 = 0x0d, // + 4 bytes + // 0x0e and 0x0f are reserved + EsStr = 0x10, + EsEnum = 0x11, // encodes the variant id as the first EsSub* + EsVec = 0x12, // encodes the # of elements as the first EsSub* + EsVecElt = 0x13, + EsMap = 0x14, // encodes the # of pairs as the first EsSub* + EsMapKey = 0x15, + EsMapVal = 0x16, + EsOpaque = 0x17, +} + +pub const NUM_IMPLICIT_TAGS: usize = 0x0e; + +#[cfg_attr(rustfmt, rustfmt_skip)] +static TAG_IMPLICIT_LEN: [i8; NUM_IMPLICIT_TAGS] = [ + 1, 2, 4, 8, // EsU* + 1, 2, 4, 8, // ESI* + 1, // EsBool + 4, // EsChar + 4, 8, // EsF* + 1, 4, // EsSub* +]; + +// rbml reading + +macro_rules! try_or { + ($e:expr, $r:expr) => ( + match $e { + Ok(e) => e, + Err(e) => { + debug!("ignored error: {:?}", e); + return $r + } + } + ) +} + +#[derive(Copy, Clone)] +pub struct Res { + pub val: usize, + pub next: usize, +} + +pub fn tag_at(data: &[u8], start: usize) -> DecodeResult { + let v = data[start] as usize; + if v < 0xf0 { + Ok(Res { + val: v, + next: start + 1, + }) + } else if v > 0xf0 { + Ok(Res { + val: ((v & 0xf) << 8) | data[start + 1] as usize, + next: start + 2, + }) + } else { + // every tag starting with byte 0xf0 is an overlong form, which is prohibited. + Err(InvalidTag(v)) + } +} + +#[inline(never)] +fn vuint_at_slow(data: &[u8], start: usize) -> DecodeResult { + let a = data[start]; + if a & 0x80 != 0 { + return Ok(Res { + val: (a & 0x7f) as usize, + next: start + 1, + }); + } + if a & 0x40 != 0 { + return Ok(Res { + val: ((a & 0x3f) as usize) << 8 | (data[start + 1] as usize), + next: start + 2, + }); + } + if a & 0x20 != 0 { + return Ok(Res { + val: ((a & 0x1f) as usize) << 16 | (data[start + 1] as usize) << 8 | + (data[start + 2] as usize), + next: start + 3, + }); + } + if a & 0x10 != 0 { + return Ok(Res { + val: ((a & 0x0f) as usize) << 24 | (data[start + 1] as usize) << 16 | + (data[start + 2] as usize) << 8 | + (data[start + 3] as usize), + next: start + 4, + }); + } + Err(IntTooBig(a as usize)) +} + +pub fn vuint_at(data: &[u8], start: usize) -> DecodeResult { + if data.len() - start < 4 { + return vuint_at_slow(data, start); + } + + // Lookup table for parsing EBML Element IDs as per + // http://ebml.sourceforge.net/specs/ The Element IDs are parsed by + // reading a big endian u32 positioned at data[start]. Using the four + // most significant bits of the u32 we lookup in the table below how + // the element ID should be derived from it. + // + // The table stores tuples (shift, mask) where shift is the number the + // u32 should be right shifted with and mask is the value the right + // shifted value should be masked with. If for example the most + // significant bit is set this means it's a class A ID and the u32 + // should be right shifted with 24 and masked with 0x7f. Therefore we + // store (24, 0x7f) at index 0x8 - 0xF (four bit numbers where the most + // significant bit is set). + // + // By storing the number of shifts and masks in a table instead of + // checking in order if the most significant bit is set, the second + // most significant bit is set etc. we can replace up to three + // "and+branch" with a single table lookup which gives us a measured + // speedup of around 2x on x86_64. + static SHIFT_MASK_TABLE: [(usize, u32); 16] = [(0, 0x0), + (0, 0x0fffffff), + (8, 0x1fffff), + (8, 0x1fffff), + (16, 0x3fff), + (16, 0x3fff), + (16, 0x3fff), + (16, 0x3fff), + (24, 0x7f), + (24, 0x7f), + (24, 0x7f), + (24, 0x7f), + (24, 0x7f), + (24, 0x7f), + (24, 0x7f), + (24, 0x7f)]; + + unsafe { + let ptr = data.as_ptr().offset(start as isize) as *const u32; + let val = u32::from_be(*ptr); + + let i = (val >> 28) as usize; + let (shift, mask) = SHIFT_MASK_TABLE[i]; + Ok(Res { + val: ((val >> shift) & mask) as usize, + next: start + ((32 - shift) >> 3), + }) + } +} + +pub fn tag_len_at(data: &[u8], tag: Res) -> DecodeResult { + if tag.val < NUM_IMPLICIT_TAGS && TAG_IMPLICIT_LEN[tag.val] >= 0 { + Ok(Res { + val: TAG_IMPLICIT_LEN[tag.val] as usize, + next: tag.next, + }) + } else { + vuint_at(data, tag.next) + } +} + +pub fn doc_at<'a>(data: &'a [u8], start: usize) -> DecodeResult> { + let elt_tag = tag_at(data, start)?; + let elt_size = tag_len_at(data, elt_tag)?; + let end = elt_size.next + elt_size.val; + Ok(TaggedDoc { + tag: elt_tag.val, + doc: Doc { + data: data, + start: elt_size.next, + end: end, + }, + }) +} + +pub fn maybe_get_doc<'a>(d: Doc<'a>, tg: usize) -> Option> { + let mut pos = d.start; + while pos < d.end { + let elt_tag = try_or!(tag_at(d.data, pos), None); + let elt_size = try_or!(tag_len_at(d.data, elt_tag), None); + pos = elt_size.next + elt_size.val; + if elt_tag.val == tg { + return Some(Doc { + data: d.data, + start: elt_size.next, + end: pos, + }); + } + } + None +} + +pub fn get_doc<'a>(d: Doc<'a>, tg: usize) -> Doc<'a> { + match maybe_get_doc(d, tg) { + Some(d) => d, + None => { + error!("failed to find block with tag {:?}", tg); + panic!(); + } + } +} + +pub fn docs<'a>(d: Doc<'a>) -> DocsIterator<'a> { + DocsIterator { d: d } +} + +pub struct DocsIterator<'a> { + d: Doc<'a>, +} + +impl<'a> Iterator for DocsIterator<'a> { + type Item = (usize, Doc<'a>); + + fn next(&mut self) -> Option<(usize, Doc<'a>)> { + if self.d.start >= self.d.end { + return None; + } + + let elt_tag = try_or!(tag_at(self.d.data, self.d.start), { + self.d.start = self.d.end; + None + }); + let elt_size = try_or!(tag_len_at(self.d.data, elt_tag), { + self.d.start = self.d.end; + None + }); + + let end = elt_size.next + elt_size.val; + let doc = Doc { + data: self.d.data, + start: elt_size.next, + end: end, + }; + + self.d.start = end; + return Some((elt_tag.val, doc)); + } +} + +pub fn tagged_docs<'a>(d: Doc<'a>, tag: usize) -> TaggedDocsIterator<'a> { + TaggedDocsIterator { + iter: docs(d), + tag: tag, + } +} + +pub struct TaggedDocsIterator<'a> { + iter: DocsIterator<'a>, + tag: usize, +} + +impl<'a> Iterator for TaggedDocsIterator<'a> { + type Item = Doc<'a>; + + fn next(&mut self) -> Option> { + while let Some((tag, doc)) = self.iter.next() { + if tag == self.tag { + return Some(doc); + } + } + None + } +} + +pub fn with_doc_data(d: Doc, f: F) -> T + where F: FnOnce(&[u8]) -> T +{ + f(&d.data[d.start..d.end]) +} + +pub fn doc_as_u8(d: Doc) -> u8 { + assert_eq!(d.end, d.start + 1); + d.data[d.start] +} + +pub fn doc_as_u64(d: Doc) -> u64 { + if d.end >= 8 { + // For performance, we read 8 big-endian bytes, + // and mask off the junk if there is any. This + // obviously won't work on the first 8 bytes + // of a file - we will fall of the start + // of the page and segfault. + + let mut b = [0; 8]; + b.copy_from_slice(&d.data[d.end - 8..d.end]); + let data = unsafe { (*(b.as_ptr() as *const u64)).to_be() }; + let len = d.end - d.start; + if len < 8 { + data & ((1 << (len * 8)) - 1) + } else { + data + } + } else { + let mut result = 0; + for b in &d.data[d.start..d.end] { + result = (result << 8) + (*b as u64); + } + result + } +} + +#[inline] +pub fn doc_as_u16(d: Doc) -> u16 { + doc_as_u64(d) as u16 +} +#[inline] +pub fn doc_as_u32(d: Doc) -> u32 { + doc_as_u64(d) as u32 +} + +#[inline] +pub fn doc_as_i8(d: Doc) -> i8 { + doc_as_u8(d) as i8 +} +#[inline] +pub fn doc_as_i16(d: Doc) -> i16 { + doc_as_u16(d) as i16 +} +#[inline] +pub fn doc_as_i32(d: Doc) -> i32 { + doc_as_u32(d) as i32 +} +#[inline] +pub fn doc_as_i64(d: Doc) -> i64 { + doc_as_u64(d) as i64 +} + +pub struct Decoder<'a> { + parent: Doc<'a>, + pos: usize, +} + +impl<'doc> Decoder<'doc> { + pub fn new(d: Doc<'doc>) -> Decoder<'doc> { + Decoder { + parent: d, + pos: d.start, + } + } + + fn next_doc(&mut self, exp_tag: EbmlEncoderTag) -> DecodeResult> { + debug!(". next_doc(exp_tag={:?})", exp_tag); + if self.pos >= self.parent.end { + return Err(Expected(format!("no more documents in current node!"))); + } + let TaggedDoc { tag: r_tag, doc: r_doc } = doc_at(self.parent.data, self.pos)?; + debug!("self.parent={:?}-{:?} self.pos={:?} r_tag={:?} r_doc={:?}-{:?}", + self.parent.start, + self.parent.end, + self.pos, + r_tag, + r_doc.start, + r_doc.end); + if r_tag != (exp_tag as usize) { + return Err(Expected(format!("expected EBML doc with tag {:?} but found tag {:?}", + exp_tag, + r_tag))); + } + if r_doc.end > self.parent.end { + return Err(Expected(format!("invalid EBML, child extends to {:#x}, parent to \ + {:#x}", + r_doc.end, + self.parent.end))); + } + self.pos = r_doc.end; + Ok(r_doc) + } + + fn push_doc(&mut self, exp_tag: EbmlEncoderTag, f: F) -> DecodeResult + where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult + { + let d = self.next_doc(exp_tag)?; + let old_parent = self.parent; + let old_pos = self.pos; + self.parent = d; + self.pos = d.start; + let r = f(self)?; + self.parent = old_parent; + self.pos = old_pos; + Ok(r) + } + + fn _next_sub(&mut self) -> DecodeResult { + // empty vector/map optimization + if self.parent.is_empty() { + return Ok(0); + } + + let TaggedDoc { tag: r_tag, doc: r_doc } = doc_at(self.parent.data, self.pos)?; + let r = if r_tag == (EsSub8 as usize) { + doc_as_u8(r_doc) as usize + } else if r_tag == (EsSub32 as usize) { + doc_as_u32(r_doc) as usize + } else { + return Err(Expected(format!("expected EBML doc with tag {:?} or {:?} but found \ + tag {:?}", + EsSub8, + EsSub32, + r_tag))); + }; + if r_doc.end > self.parent.end { + return Err(Expected(format!("invalid EBML, child extends to {:#x}, parent to \ + {:#x}", + r_doc.end, + self.parent.end))); + } + self.pos = r_doc.end; + debug!("_next_sub result={:?}", r); + Ok(r) + } + + // variable-length unsigned integer with different tags. + // `first_tag` should be a tag for u8 or i8. + // `last_tag` should be the largest allowed integer tag with the matching signedness. + // all tags between them should be valid, in the order of u8, u16, u32 and u64. + fn _next_int(&mut self, + first_tag: EbmlEncoderTag, + last_tag: EbmlEncoderTag) + -> DecodeResult { + if self.pos >= self.parent.end { + return Err(Expected(format!("no more documents in current node!"))); + } + + let TaggedDoc { tag: r_tag, doc: r_doc } = doc_at(self.parent.data, self.pos)?; + let r = if first_tag as usize <= r_tag && r_tag <= last_tag as usize { + match r_tag - first_tag as usize { + 0 => doc_as_u8(r_doc) as u64, + 1 => doc_as_u16(r_doc) as u64, + 2 => doc_as_u32(r_doc) as u64, + 3 => doc_as_u64(r_doc), + _ => unreachable!(), + } + } else { + return Err(Expected(format!("expected EBML doc with tag {:?} through {:?} but \ + found tag {:?}", + first_tag, + last_tag, + r_tag))); + }; + if r_doc.end > self.parent.end { + return Err(Expected(format!("invalid EBML, child extends to {:#x}, parent to \ + {:#x}", + r_doc.end, + self.parent.end))); + } + self.pos = r_doc.end; + debug!("_next_int({:?}, {:?}) result={:?}", first_tag, last_tag, r); + Ok(r) + } + + pub fn read_opaque(&mut self, op: F) -> DecodeResult + where F: FnOnce(&mut opaque::Decoder, Doc) -> DecodeResult + { + let doc = self.next_doc(EsOpaque)?; + + let result = { + let mut opaque_decoder = opaque::Decoder::new(doc.data, doc.start); + op(&mut opaque_decoder, doc)? + }; + + Ok(result) + } + + pub fn position(&self) -> usize { + self.pos + } + + pub fn advance(&mut self, bytes: usize) { + self.pos += bytes; + } +} + +impl<'doc> serialize::Decoder for Decoder<'doc> { + type Error = Error; + fn read_nil(&mut self) -> DecodeResult<()> { + Ok(()) + } + + fn read_u64(&mut self) -> DecodeResult { + self._next_int(EsU8, EsU64) + } + fn read_u32(&mut self) -> DecodeResult { + Ok(self._next_int(EsU8, EsU32)? as u32) + } + fn read_u16(&mut self) -> DecodeResult { + Ok(self._next_int(EsU8, EsU16)? as u16) + } + fn read_u8(&mut self) -> DecodeResult { + Ok(doc_as_u8(self.next_doc(EsU8)?)) + } + fn read_usize(&mut self) -> DecodeResult { + let v = self._next_int(EsU8, EsU64)?; + if v > (::std::usize::MAX as u64) { + Err(IntTooBig(v as usize)) + } else { + Ok(v as usize) + } + } + + fn read_i64(&mut self) -> DecodeResult { + Ok(self._next_int(EsI8, EsI64)? as i64) + } + fn read_i32(&mut self) -> DecodeResult { + Ok(self._next_int(EsI8, EsI32)? as i32) + } + fn read_i16(&mut self) -> DecodeResult { + Ok(self._next_int(EsI8, EsI16)? as i16) + } + fn read_i8(&mut self) -> DecodeResult { + Ok(doc_as_u8(self.next_doc(EsI8)?) as i8) + } + fn read_isize(&mut self) -> DecodeResult { + let v = self._next_int(EsI8, EsI64)? as i64; + if v > (isize::MAX as i64) || v < (isize::MIN as i64) { + debug!("FIXME \\#6122: Removing this makes this function miscompile"); + Err(IntTooBig(v as usize)) + } else { + Ok(v as isize) + } + } + + fn read_bool(&mut self) -> DecodeResult { + Ok(doc_as_u8(self.next_doc(EsBool)?) != 0) + } + + fn read_f64(&mut self) -> DecodeResult { + let bits = doc_as_u64(self.next_doc(EsF64)?); + Ok(unsafe { transmute(bits) }) + } + fn read_f32(&mut self) -> DecodeResult { + let bits = doc_as_u32(self.next_doc(EsF32)?); + Ok(unsafe { transmute(bits) }) + } + fn read_char(&mut self) -> DecodeResult { + Ok(char::from_u32(doc_as_u32(self.next_doc(EsChar)?)).unwrap()) + } + fn read_str(&mut self) -> DecodeResult { + Ok(self.next_doc(EsStr)?.to_string()) + } + + // Compound types: + fn read_enum(&mut self, name: &str, f: F) -> DecodeResult + where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult + { + debug!("read_enum({})", name); + + let doc = self.next_doc(EsEnum)?; + + let (old_parent, old_pos) = (self.parent, self.pos); + self.parent = doc; + self.pos = self.parent.start; + + let result = f(self)?; + + self.parent = old_parent; + self.pos = old_pos; + Ok(result) + } + + fn read_enum_variant(&mut self, _: &[&str], mut f: F) -> DecodeResult + where F: FnMut(&mut Decoder<'doc>, usize) -> DecodeResult + { + debug!("read_enum_variant()"); + let idx = self._next_sub()?; + debug!(" idx={}", idx); + + f(self, idx) + } + + fn read_enum_variant_arg(&mut self, idx: usize, f: F) -> DecodeResult + where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult + { + debug!("read_enum_variant_arg(idx={})", idx); + f(self) + } + + fn read_enum_struct_variant(&mut self, _: &[&str], mut f: F) -> DecodeResult + where F: FnMut(&mut Decoder<'doc>, usize) -> DecodeResult + { + debug!("read_enum_struct_variant()"); + let idx = self._next_sub()?; + debug!(" idx={}", idx); + + f(self, idx) + } + + fn read_enum_struct_variant_field(&mut self, + name: &str, + idx: usize, + f: F) + -> DecodeResult + where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult + { + debug!("read_enum_struct_variant_arg(name={}, idx={})", name, idx); + f(self) + } + + fn read_struct(&mut self, name: &str, _: usize, f: F) -> DecodeResult + where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult + { + debug!("read_struct(name={})", name); + f(self) + } + + fn read_struct_field(&mut self, name: &str, idx: usize, f: F) -> DecodeResult + where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult + { + debug!("read_struct_field(name={}, idx={})", name, idx); + f(self) + } + + fn read_tuple(&mut self, tuple_len: usize, f: F) -> DecodeResult + where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult + { + debug!("read_tuple()"); + self.read_seq(move |d, len| { + if len == tuple_len { + f(d) + } else { + Err(Expected(format!("Expected tuple of length `{}`, found tuple of length \ + `{}`", + tuple_len, + len))) + } + }) + } + + fn read_tuple_arg(&mut self, idx: usize, f: F) -> DecodeResult + where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult + { + debug!("read_tuple_arg(idx={})", idx); + self.read_seq_elt(idx, f) + } + + fn read_tuple_struct(&mut self, name: &str, len: usize, f: F) -> DecodeResult + where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult + { + debug!("read_tuple_struct(name={})", name); + self.read_tuple(len, f) + } + + fn read_tuple_struct_arg(&mut self, idx: usize, f: F) -> DecodeResult + where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult + { + debug!("read_tuple_struct_arg(idx={})", idx); + self.read_tuple_arg(idx, f) + } + + fn read_option(&mut self, mut f: F) -> DecodeResult + where F: FnMut(&mut Decoder<'doc>, bool) -> DecodeResult + { + debug!("read_option()"); + self.read_enum("Option", move |this| { + this.read_enum_variant(&["None", "Some"], move |this, idx| { + match idx { + 0 => f(this, false), + 1 => f(this, true), + _ => Err(Expected(format!("Expected None or Some"))), + } + }) + }) + } + + fn read_seq(&mut self, f: F) -> DecodeResult + where F: FnOnce(&mut Decoder<'doc>, usize) -> DecodeResult + { + debug!("read_seq()"); + self.push_doc(EsVec, move |d| { + let len = d._next_sub()?; + debug!(" len={}", len); + f(d, len) + }) + } + + fn read_seq_elt(&mut self, idx: usize, f: F) -> DecodeResult + where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult + { + debug!("read_seq_elt(idx={})", idx); + self.push_doc(EsVecElt, f) + } + + fn read_map(&mut self, f: F) -> DecodeResult + where F: FnOnce(&mut Decoder<'doc>, usize) -> DecodeResult + { + debug!("read_map()"); + self.push_doc(EsMap, move |d| { + let len = d._next_sub()?; + debug!(" len={}", len); + f(d, len) + }) + } + + fn read_map_elt_key(&mut self, idx: usize, f: F) -> DecodeResult + where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult + { + debug!("read_map_elt_key(idx={})", idx); + self.push_doc(EsMapKey, f) + } + + fn read_map_elt_val(&mut self, idx: usize, f: F) -> DecodeResult + where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult + { + debug!("read_map_elt_val(idx={})", idx); + self.push_doc(EsMapVal, f) + } + + fn error(&mut self, err: &str) -> Error { + ApplicationError(err.to_string()) + } +} + +#[test] +fn test_vuint_at() { + let data = &[ + 0x80, + 0xff, + 0x40, 0x00, + 0x7f, 0xff, + 0x20, 0x00, 0x00, + 0x3f, 0xff, 0xff, + 0x10, 0x00, 0x00, 0x00, + 0x1f, 0xff, 0xff, 0xff + ]; + + let mut res: Res; + + // Class A + res = vuint_at(data, 0).unwrap(); + assert_eq!(res.val, 0); + assert_eq!(res.next, 1); + res = vuint_at(data, res.next).unwrap(); + assert_eq!(res.val, (1 << 7) - 1); + assert_eq!(res.next, 2); + + // Class B + res = vuint_at(data, res.next).unwrap(); + assert_eq!(res.val, 0); + assert_eq!(res.next, 4); + res = vuint_at(data, res.next).unwrap(); + assert_eq!(res.val, (1 << 14) - 1); + assert_eq!(res.next, 6); + + // Class C + res = vuint_at(data, res.next).unwrap(); + assert_eq!(res.val, 0); + assert_eq!(res.next, 9); + res = vuint_at(data, res.next).unwrap(); + assert_eq!(res.val, (1 << 21) - 1); + assert_eq!(res.next, 12); + + // Class D + res = vuint_at(data, res.next).unwrap(); + assert_eq!(res.val, 0); + assert_eq!(res.next, 16); + res = vuint_at(data, res.next).unwrap(); + assert_eq!(res.val, (1 << 28) - 1); + assert_eq!(res.next, 20); +} + +#[bench] +pub fn vuint_at_A_aligned(b: &mut Bencher) { + let data = (0..4 * 100) + .map(|i| { + match i % 2 { + 0 => 0x80, + _ => i as u8, + } + }) + .collect::>(); + let mut sum = 0; + b.iter(|| { + let mut i = 0; + while i < data.len() { + sum += vuint_at(&data, i).unwrap().val; + i += 4; + } + }); +} + +#[bench] +pub fn vuint_at_A_unaligned(b: &mut Bencher) { + let data = (0..4 * 100 + 1) + .map(|i| { + match i % 2 { + 1 => 0x80, + _ => i as u8, + } + }) + .collect::>(); + let mut sum = 0; + b.iter(|| { + let mut i = 1; + while i < data.len() { + sum += vuint_at(&data, i).unwrap().val; + i += 4; + } + }); +} + +#[bench] +pub fn vuint_at_D_aligned(b: &mut Bencher) { + let data = (0..4 * 100) + .map(|i| { + match i % 4 { + 0 => 0x10, + 3 => i as u8, + _ => 0, + } + }) + .collect::>(); + let mut sum = 0; + b.iter(|| { + let mut i = 0; + while i < data.len() { + sum += vuint_at(&data, i).unwrap().val; + i += 4; + } + }); +} + +#[bench] +pub fn vuint_at_D_unaligned(b: &mut Bencher) { + let data = (0..4 * 100 + 1) + .map(|i| { + match i % 4 { + 1 => 0x10, + 0 => i as u8, + _ => 0, + } + }) + .collect::>(); + let mut sum = 0; + b.iter(|| { + let mut i = 1; + while i < data.len() { + sum += vuint_at(&data, i).unwrap().val; + i += 4; + } + }); +} diff --git a/src/librustc_metadata/rbml/writer.rs b/src/librustc_metadata/rbml/writer.rs new file mode 100644 index 0000000000000..d6f4b0d03f22c --- /dev/null +++ b/src/librustc_metadata/rbml/writer.rs @@ -0,0 +1,522 @@ +// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::mem; +use std::io::prelude::*; +use std::io::{self, SeekFrom, Cursor}; + +use rbml::opaque; +use rbml::reader::EbmlEncoderTag::*; +use rbml::reader::NUM_IMPLICIT_TAGS; + +use rustc_serialize as serialize; + +pub type EncodeResult = io::Result<()>; + +// rbml writing +pub struct Encoder<'a> { + pub writer: &'a mut Cursor>, + size_positions: Vec, + relax_limit: u64, // do not move encoded bytes before this position +} + +const NUM_TAGS: usize = 0x1000; + +fn write_tag(w: &mut W, n: usize) -> EncodeResult { + if n < 0xf0 { + w.write_all(&[n as u8]) + } else if 0x100 <= n && n < NUM_TAGS { + w.write_all(&[0xf0 | (n >> 8) as u8, n as u8]) + } else { + Err(io::Error::new(io::ErrorKind::Other, &format!("invalid tag: {}", n)[..])) + } +} + +fn write_sized_vuint(w: &mut W, n: usize, size: usize) -> EncodeResult { + match size { + 1 => w.write_all(&[0x80 | (n as u8)]), + 2 => w.write_all(&[0x40 | ((n >> 8) as u8), n as u8]), + 3 => w.write_all(&[0x20 | ((n >> 16) as u8), (n >> 8) as u8, n as u8]), + 4 => w.write_all(&[0x10 | ((n >> 24) as u8), (n >> 16) as u8, (n >> 8) as u8, n as u8]), + _ => Err(io::Error::new(io::ErrorKind::Other, &format!("isize too big: {}", n)[..])), + } +} + +pub fn write_vuint(w: &mut W, n: usize) -> EncodeResult { + if n < 0x7f { + return write_sized_vuint(w, n, 1); + } + if n < 0x4000 { + return write_sized_vuint(w, n, 2); + } + if n < 0x200000 { + return write_sized_vuint(w, n, 3); + } + if n < 0x10000000 { + return write_sized_vuint(w, n, 4); + } + Err(io::Error::new(io::ErrorKind::Other, &format!("isize too big: {}", n)[..])) +} + +impl<'a> Encoder<'a> { + pub fn new(w: &'a mut Cursor>) -> Encoder<'a> { + Encoder { + writer: w, + size_positions: vec![], + relax_limit: 0, + } + } + + pub fn start_tag(&mut self, tag_id: usize) -> EncodeResult { + debug!("Start tag {:?}", tag_id); + assert!(tag_id >= NUM_IMPLICIT_TAGS); + + // Write the enum ID: + write_tag(self.writer, tag_id)?; + + // Write a placeholder four-byte size. + let cur_pos = self.writer.seek(SeekFrom::Current(0))?; + self.size_positions.push(cur_pos); + let zeroes: &[u8] = &[0, 0, 0, 0]; + self.writer.write_all(zeroes) + } + + pub fn end_tag(&mut self) -> EncodeResult { + let last_size_pos = self.size_positions.pop().unwrap(); + let cur_pos = self.writer.seek(SeekFrom::Current(0))?; + self.writer.seek(SeekFrom::Start(last_size_pos))?; + let size = (cur_pos - last_size_pos - 4) as usize; + + // relax the size encoding for small tags (bigger tags are costly to move). + // we should never try to move the stable positions, however. + const RELAX_MAX_SIZE: usize = 0x100; + if size <= RELAX_MAX_SIZE && last_size_pos >= self.relax_limit { + // we can't alter the buffer in place, so have a temporary buffer + let mut buf = [0u8; RELAX_MAX_SIZE]; + { + let last_size_pos = last_size_pos as usize; + let data = &self.writer.get_ref()[last_size_pos + 4..cur_pos as usize]; + buf[..size].copy_from_slice(data); + } + + // overwrite the size and data and continue + write_vuint(self.writer, size)?; + self.writer.write_all(&buf[..size])?; + } else { + // overwrite the size with an overlong encoding and skip past the data + write_sized_vuint(self.writer, size, 4)?; + self.writer.seek(SeekFrom::Start(cur_pos))?; + } + + debug!("End tag (size = {:?})", size); + Ok(()) + } + + pub fn wr_tag(&mut self, tag_id: usize, blk: F) -> EncodeResult + where F: FnOnce() -> EncodeResult + { + self.start_tag(tag_id)?; + blk()?; + self.end_tag() + } + + pub fn wr_tagged_bytes(&mut self, tag_id: usize, b: &[u8]) -> EncodeResult { + assert!(tag_id >= NUM_IMPLICIT_TAGS); + write_tag(self.writer, tag_id)?; + write_vuint(self.writer, b.len())?; + self.writer.write_all(b) + } + + pub fn wr_tagged_u64(&mut self, tag_id: usize, v: u64) -> EncodeResult { + let bytes: [u8; 8] = unsafe { mem::transmute(v.to_be()) }; + // tagged integers are emitted in big-endian, with no + // leading zeros. + let leading_zero_bytes = v.leading_zeros() / 8; + self.wr_tagged_bytes(tag_id, &bytes[leading_zero_bytes as usize..]) + } + + #[inline] + pub fn wr_tagged_u32(&mut self, tag_id: usize, v: u32) -> EncodeResult { + self.wr_tagged_u64(tag_id, v as u64) + } + + #[inline] + pub fn wr_tagged_u16(&mut self, tag_id: usize, v: u16) -> EncodeResult { + self.wr_tagged_u64(tag_id, v as u64) + } + + #[inline] + pub fn wr_tagged_u8(&mut self, tag_id: usize, v: u8) -> EncodeResult { + self.wr_tagged_bytes(tag_id, &[v]) + } + + #[inline] + pub fn wr_tagged_i64(&mut self, tag_id: usize, v: i64) -> EncodeResult { + self.wr_tagged_u64(tag_id, v as u64) + } + + #[inline] + pub fn wr_tagged_i32(&mut self, tag_id: usize, v: i32) -> EncodeResult { + self.wr_tagged_u32(tag_id, v as u32) + } + + #[inline] + pub fn wr_tagged_i16(&mut self, tag_id: usize, v: i16) -> EncodeResult { + self.wr_tagged_u16(tag_id, v as u16) + } + + #[inline] + pub fn wr_tagged_i8(&mut self, tag_id: usize, v: i8) -> EncodeResult { + self.wr_tagged_bytes(tag_id, &[v as u8]) + } + + pub fn wr_tagged_str(&mut self, tag_id: usize, v: &str) -> EncodeResult { + self.wr_tagged_bytes(tag_id, v.as_bytes()) + } + + // for auto-serialization + fn wr_tagged_raw_bytes(&mut self, tag_id: usize, b: &[u8]) -> EncodeResult { + write_tag(self.writer, tag_id)?; + self.writer.write_all(b) + } + + fn wr_tagged_raw_u64(&mut self, tag_id: usize, v: u64) -> EncodeResult { + let bytes: [u8; 8] = unsafe { mem::transmute(v.to_be()) }; + self.wr_tagged_raw_bytes(tag_id, &bytes) + } + + fn wr_tagged_raw_u32(&mut self, tag_id: usize, v: u32) -> EncodeResult { + let bytes: [u8; 4] = unsafe { mem::transmute(v.to_be()) }; + self.wr_tagged_raw_bytes(tag_id, &bytes) + } + + fn wr_tagged_raw_u16(&mut self, tag_id: usize, v: u16) -> EncodeResult { + let bytes: [u8; 2] = unsafe { mem::transmute(v.to_be()) }; + self.wr_tagged_raw_bytes(tag_id, &bytes) + } + + fn wr_tagged_raw_u8(&mut self, tag_id: usize, v: u8) -> EncodeResult { + self.wr_tagged_raw_bytes(tag_id, &[v]) + } + + fn wr_tagged_raw_i64(&mut self, tag_id: usize, v: i64) -> EncodeResult { + self.wr_tagged_raw_u64(tag_id, v as u64) + } + + fn wr_tagged_raw_i32(&mut self, tag_id: usize, v: i32) -> EncodeResult { + self.wr_tagged_raw_u32(tag_id, v as u32) + } + + fn wr_tagged_raw_i16(&mut self, tag_id: usize, v: i16) -> EncodeResult { + self.wr_tagged_raw_u16(tag_id, v as u16) + } + + fn wr_tagged_raw_i8(&mut self, tag_id: usize, v: i8) -> EncodeResult { + self.wr_tagged_raw_bytes(tag_id, &[v as u8]) + } + + pub fn wr_bytes(&mut self, b: &[u8]) -> EncodeResult { + debug!("Write {:?} bytes", b.len()); + self.writer.write_all(b) + } + + pub fn wr_str(&mut self, s: &str) -> EncodeResult { + debug!("Write str: {:?}", s); + self.writer.write_all(s.as_bytes()) + } + + /// Returns the current position while marking it stable, i.e. + /// generated bytes so far wouldn't be affected by relaxation. + pub fn mark_stable_position(&mut self) -> u64 { + let pos = self.writer.seek(SeekFrom::Current(0)).unwrap(); + if self.relax_limit < pos { + self.relax_limit = pos; + } + pos + } +} + +impl<'a> Encoder<'a> { + // used internally to emit things like the vector length and so on + fn _emit_tagged_sub(&mut self, v: usize) -> EncodeResult { + if v as u8 as usize == v { + self.wr_tagged_raw_u8(EsSub8 as usize, v as u8) + } else if v as u32 as usize == v { + self.wr_tagged_raw_u32(EsSub32 as usize, v as u32) + } else { + Err(io::Error::new(io::ErrorKind::Other, + &format!("length or variant id too big: {}", v)[..])) + } + } + + pub fn emit_opaque(&mut self, f: F) -> EncodeResult + where F: FnOnce(&mut opaque::Encoder) -> EncodeResult + { + self.start_tag(EsOpaque as usize)?; + + { + let mut opaque_encoder = opaque::Encoder::new(self.writer); + f(&mut opaque_encoder)?; + } + + self.mark_stable_position(); + self.end_tag() + } +} + +impl<'a> serialize::Encoder for Encoder<'a> { + type Error = io::Error; + + fn emit_nil(&mut self) -> EncodeResult { + Ok(()) + } + + fn emit_usize(&mut self, v: usize) -> EncodeResult { + self.emit_u64(v as u64) + } + fn emit_u64(&mut self, v: u64) -> EncodeResult { + if v as u32 as u64 == v { + self.emit_u32(v as u32) + } else { + self.wr_tagged_raw_u64(EsU64 as usize, v) + } + } + fn emit_u32(&mut self, v: u32) -> EncodeResult { + if v as u16 as u32 == v { + self.emit_u16(v as u16) + } else { + self.wr_tagged_raw_u32(EsU32 as usize, v) + } + } + fn emit_u16(&mut self, v: u16) -> EncodeResult { + if v as u8 as u16 == v { + self.emit_u8(v as u8) + } else { + self.wr_tagged_raw_u16(EsU16 as usize, v) + } + } + fn emit_u8(&mut self, v: u8) -> EncodeResult { + self.wr_tagged_raw_u8(EsU8 as usize, v) + } + + fn emit_isize(&mut self, v: isize) -> EncodeResult { + self.emit_i64(v as i64) + } + fn emit_i64(&mut self, v: i64) -> EncodeResult { + if v as i32 as i64 == v { + self.emit_i32(v as i32) + } else { + self.wr_tagged_raw_i64(EsI64 as usize, v) + } + } + fn emit_i32(&mut self, v: i32) -> EncodeResult { + if v as i16 as i32 == v { + self.emit_i16(v as i16) + } else { + self.wr_tagged_raw_i32(EsI32 as usize, v) + } + } + fn emit_i16(&mut self, v: i16) -> EncodeResult { + if v as i8 as i16 == v { + self.emit_i8(v as i8) + } else { + self.wr_tagged_raw_i16(EsI16 as usize, v) + } + } + fn emit_i8(&mut self, v: i8) -> EncodeResult { + self.wr_tagged_raw_i8(EsI8 as usize, v) + } + + fn emit_bool(&mut self, v: bool) -> EncodeResult { + self.wr_tagged_raw_u8(EsBool as usize, v as u8) + } + + fn emit_f64(&mut self, v: f64) -> EncodeResult { + let bits = unsafe { mem::transmute(v) }; + self.wr_tagged_raw_u64(EsF64 as usize, bits) + } + fn emit_f32(&mut self, v: f32) -> EncodeResult { + let bits = unsafe { mem::transmute(v) }; + self.wr_tagged_raw_u32(EsF32 as usize, bits) + } + fn emit_char(&mut self, v: char) -> EncodeResult { + self.wr_tagged_raw_u32(EsChar as usize, v as u32) + } + + fn emit_str(&mut self, v: &str) -> EncodeResult { + self.wr_tagged_str(EsStr as usize, v) + } + + fn emit_enum(&mut self, _name: &str, f: F) -> EncodeResult + where F: FnOnce(&mut Encoder<'a>) -> EncodeResult + { + self.start_tag(EsEnum as usize)?; + f(self)?; + self.end_tag() + } + + fn emit_enum_variant(&mut self, _: &str, v_id: usize, _: usize, f: F) -> EncodeResult + where F: FnOnce(&mut Encoder<'a>) -> EncodeResult + { + self._emit_tagged_sub(v_id)?; + f(self) + } + + fn emit_enum_variant_arg(&mut self, _: usize, f: F) -> EncodeResult + where F: FnOnce(&mut Encoder<'a>) -> EncodeResult + { + f(self) + } + + fn emit_enum_struct_variant(&mut self, + v_name: &str, + v_id: usize, + cnt: usize, + f: F) + -> EncodeResult + where F: FnOnce(&mut Encoder<'a>) -> EncodeResult + { + self.emit_enum_variant(v_name, v_id, cnt, f) + } + + fn emit_enum_struct_variant_field(&mut self, _: &str, idx: usize, f: F) -> EncodeResult + where F: FnOnce(&mut Encoder<'a>) -> EncodeResult + { + self.emit_enum_variant_arg(idx, f) + } + + fn emit_struct(&mut self, _: &str, _len: usize, f: F) -> EncodeResult + where F: FnOnce(&mut Encoder<'a>) -> EncodeResult + { + f(self) + } + + fn emit_struct_field(&mut self, _name: &str, _: usize, f: F) -> EncodeResult + where F: FnOnce(&mut Encoder<'a>) -> EncodeResult + { + f(self) + } + + fn emit_tuple(&mut self, len: usize, f: F) -> EncodeResult + where F: FnOnce(&mut Encoder<'a>) -> EncodeResult + { + self.emit_seq(len, f) + } + fn emit_tuple_arg(&mut self, idx: usize, f: F) -> EncodeResult + where F: FnOnce(&mut Encoder<'a>) -> EncodeResult + { + self.emit_seq_elt(idx, f) + } + + fn emit_tuple_struct(&mut self, _: &str, len: usize, f: F) -> EncodeResult + where F: FnOnce(&mut Encoder<'a>) -> EncodeResult + { + self.emit_seq(len, f) + } + fn emit_tuple_struct_arg(&mut self, idx: usize, f: F) -> EncodeResult + where F: FnOnce(&mut Encoder<'a>) -> EncodeResult + { + self.emit_seq_elt(idx, f) + } + + fn emit_option(&mut self, f: F) -> EncodeResult + where F: FnOnce(&mut Encoder<'a>) -> EncodeResult + { + self.emit_enum("Option", f) + } + fn emit_option_none(&mut self) -> EncodeResult { + self.emit_enum_variant("None", 0, 0, |_| Ok(())) + } + fn emit_option_some(&mut self, f: F) -> EncodeResult + where F: FnOnce(&mut Encoder<'a>) -> EncodeResult + { + + self.emit_enum_variant("Some", 1, 1, f) + } + + fn emit_seq(&mut self, len: usize, f: F) -> EncodeResult + where F: FnOnce(&mut Encoder<'a>) -> EncodeResult + { + if len == 0 { + // empty vector optimization + return self.wr_tagged_bytes(EsVec as usize, &[]); + } + + self.start_tag(EsVec as usize)?; + self._emit_tagged_sub(len)?; + f(self)?; + self.end_tag() + } + + fn emit_seq_elt(&mut self, _idx: usize, f: F) -> EncodeResult + where F: FnOnce(&mut Encoder<'a>) -> EncodeResult + { + + self.start_tag(EsVecElt as usize)?; + f(self)?; + self.end_tag() + } + + fn emit_map(&mut self, len: usize, f: F) -> EncodeResult + where F: FnOnce(&mut Encoder<'a>) -> EncodeResult + { + if len == 0 { + // empty map optimization + return self.wr_tagged_bytes(EsMap as usize, &[]); + } + + self.start_tag(EsMap as usize)?; + self._emit_tagged_sub(len)?; + f(self)?; + self.end_tag() + } + + fn emit_map_elt_key(&mut self, _idx: usize, f: F) -> EncodeResult + where F: FnOnce(&mut Encoder<'a>) -> EncodeResult + { + + self.start_tag(EsMapKey as usize)?; + f(self)?; + self.end_tag() + } + + fn emit_map_elt_val(&mut self, _idx: usize, f: F) -> EncodeResult + where F: FnOnce(&mut Encoder<'a>) -> EncodeResult + { + self.start_tag(EsMapVal as usize)?; + f(self)?; + self.end_tag() + } +} + +#[test] +fn test_option_int() { + use rbml::reader; + use serialize::{Encodable, Decodable}; + use std::io::Cursor; + + fn test_v(v: Option) { + debug!("v == {:?}", v); + let mut wr = Cursor::new(Vec::new()); + { + let mut rbml_w = Encoder::new(&mut wr); + let _ = v.encode(&mut rbml_w); + } + let rbml_doc = reader::Doc::new(wr.get_ref()); + let mut deser = reader::Decoder::new(rbml_doc); + let v1 = Decodable::decode(&mut deser).unwrap(); + debug!("v1 == {:?}", v1); + assert_eq!(v, v1); + } + + test_v(Some(22)); + test_v(None); + test_v(Some(3)); +} From 87db6b9e65d3ee67f2c3ff8312fa7fbbe89ac8e9 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Mon, 29 Aug 2016 03:33:38 +0300 Subject: [PATCH 03/39] rustc_metadata: remove redundant lifetimes from astencode::DecodeContext. --- src/librustc_metadata/astencode.rs | 106 ++++++++++++++--------------- 1 file changed, 52 insertions(+), 54 deletions(-) diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs index fb7e1c0f7895e..4469a797eed9b 100644 --- a/src/librustc_metadata/astencode.rs +++ b/src/librustc_metadata/astencode.rs @@ -58,9 +58,9 @@ use rustc_serialize::{Encodable, EncoderHelpers}; #[cfg(test)] use rustc::hir::print as pprust; #[cfg(test)] use rustc::hir::lowering::{LoweringContext, DummyResolver}; -struct DecodeContext<'a, 'b, 'tcx: 'a> { +struct DecodeContext<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, - cdata: &'b cstore::CrateMetadata, + cdata: &'a cstore::CrateMetadata, from_id_range: IdRange, to_id_range: IdRange, // Cache the last used filemap for translating spans as an optimization. @@ -102,7 +102,7 @@ pub fn encode_inlined_item(ecx: &e::EncodeContext, rbml_w.writer.seek(SeekFrom::Current(0))); } -impl<'a, 'b, 'c, 'tcx> ast_map::FoldOps for &'a DecodeContext<'b, 'c, 'tcx> { +impl<'a, 'b, 'tcx> ast_map::FoldOps for &'a DecodeContext<'b, 'tcx> { fn new_id(&self, id: ast::NodeId) -> ast::NodeId { if id == ast::DUMMY_NODE_ID { // Used by ast_map to map the NodeInlinedParent. @@ -177,7 +177,7 @@ fn reserve_id_range(sess: &Session, IdRange { min: to_id_min, max: to_id_max } } -impl<'a, 'b, 'tcx> DecodeContext<'a, 'b, 'tcx> { +impl<'a, 'tcx> DecodeContext<'a, 'tcx> { /// Translates an internal id, meaning a node id that is known to refer to some part of the /// item currently being inlined, such as a local variable or argument. All naked node-ids /// that appear in types have this property, since if something might refer to an external item @@ -462,8 +462,8 @@ impl tr for hir::Freevar { // Encoding and decoding of MethodCallee trait read_method_callee_helper<'tcx> { - fn read_method_callee<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>) - -> (u32, ty::MethodCallee<'tcx>); + fn read_method_callee<'a>(&mut self, dcx: &DecodeContext<'a, 'tcx>) + -> (u32, ty::MethodCallee<'tcx>); } fn encode_method_callee<'a, 'tcx>(ecx: &e::EncodeContext<'a, 'tcx>, @@ -489,8 +489,8 @@ fn encode_method_callee<'a, 'tcx>(ecx: &e::EncodeContext<'a, 'tcx>, } impl<'a, 'tcx> read_method_callee_helper<'tcx> for reader::Decoder<'a> { - fn read_method_callee<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>) - -> (u32, ty::MethodCallee<'tcx>) { + fn read_method_callee<'b>(&mut self, dcx: &DecodeContext<'b, 'tcx>) + -> (u32, ty::MethodCallee<'tcx>) { self.read_struct("MethodCallee", 4, |this| { let autoderef = this.read_struct_field("autoderef", 0, @@ -821,31 +821,30 @@ impl<'a> doc_decoder_helpers for rbml::Doc<'a> { } trait rbml_decoder_decoder_helpers<'tcx> { - fn read_ty_encoded<'a, 'b, F, R>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>, - f: F) -> R + fn read_ty_encoded<'a, F, R>(&mut self, dcx: &DecodeContext<'a, 'tcx>, f: F) -> R where F: for<'x> FnOnce(&mut tydecode::TyDecoder<'x, 'tcx>) -> R; - fn read_region<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>) -> &'tcx ty::Region; - fn read_ty<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>) -> Ty<'tcx>; - fn read_tys<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>) -> Vec>; - fn read_trait_ref<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>) - -> ty::TraitRef<'tcx>; - fn read_poly_trait_ref<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>) - -> ty::PolyTraitRef<'tcx>; - fn read_predicate<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>) - -> ty::Predicate<'tcx>; - fn read_substs<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>) - -> &'tcx Substs<'tcx>; - fn read_upvar_capture<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>) - -> ty::UpvarCapture<'tcx>; - fn read_auto_adjustment<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>) - -> adjustment::AutoAdjustment<'tcx>; - fn read_cast_kind<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>) - -> cast::CastKind; - fn read_auto_deref_ref<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>) - -> adjustment::AutoDerefRef<'tcx>; - fn read_autoref<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>) - -> adjustment::AutoRef<'tcx>; + fn read_region<'a>(&mut self, dcx: &DecodeContext<'a, 'tcx>) -> &'tcx ty::Region; + fn read_ty<'a>(&mut self, dcx: &DecodeContext<'a, 'tcx>) -> Ty<'tcx>; + fn read_tys<'a>(&mut self, dcx: &DecodeContext<'a, 'tcx>) -> Vec>; + fn read_trait_ref<'a>(&mut self, dcx: &DecodeContext<'a, 'tcx>) + -> ty::TraitRef<'tcx>; + fn read_poly_trait_ref<'a>(&mut self, dcx: &DecodeContext<'a, 'tcx>) + -> ty::PolyTraitRef<'tcx>; + fn read_predicate<'a>(&mut self, dcx: &DecodeContext<'a, 'tcx>) + -> ty::Predicate<'tcx>; + fn read_substs<'a>(&mut self, dcx: &DecodeContext<'a, 'tcx>) + -> &'tcx Substs<'tcx>; + fn read_upvar_capture<'a>(&mut self, dcx: &DecodeContext<'a, 'tcx>) + -> ty::UpvarCapture<'tcx>; + fn read_auto_adjustment<'a>(&mut self, dcx: &DecodeContext<'a, 'tcx>) + -> adjustment::AutoAdjustment<'tcx>; + fn read_cast_kind<'a>(&mut self, dcx: &DecodeContext<'a, 'tcx>) + -> cast::CastKind; + fn read_auto_deref_ref<'a>(&mut self, dcx: &DecodeContext<'a, 'tcx>) + -> adjustment::AutoDerefRef<'tcx>; + fn read_autoref<'a>(&mut self, dcx: &DecodeContext<'a, 'tcx>) + -> adjustment::AutoRef<'tcx>; // Versions of the type reading functions that don't need the full // DecodeContext. @@ -890,7 +889,7 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> { }).unwrap() } - fn read_ty_encoded<'b, 'c, F, R>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>, op: F) -> R + fn read_ty_encoded<'b, F, R>(&mut self, dcx: &DecodeContext<'b, 'tcx>, op: F) -> R where F: for<'x> FnOnce(&mut tydecode::TyDecoder<'x,'tcx>) -> R { return self.read_opaque(|_, doc| { @@ -909,48 +908,47 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> { str } } - fn read_region<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>) -> &'tcx ty::Region { + fn read_region<'b>(&mut self, dcx: &DecodeContext<'b, 'tcx>) -> &'tcx ty::Region { // Note: regions types embed local node ids. In principle, we // should translate these node ids into the new decode // context. However, we do not bother, because region types // are not used during trans. This also applies to read_ty. return self.read_ty_encoded(dcx, |decoder| decoder.parse_region()); } - fn read_ty<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>) -> Ty<'tcx> { + fn read_ty<'b>(&mut self, dcx: &DecodeContext<'b, 'tcx>) -> Ty<'tcx> { return self.read_ty_encoded(dcx, |decoder| decoder.parse_ty()); } - fn read_tys<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>) - -> Vec> { + fn read_tys<'b>(&mut self, dcx: &DecodeContext<'b, 'tcx>) -> Vec> { self.read_to_vec(|this| Ok(this.read_ty(dcx))).unwrap().into_iter().collect() } - fn read_trait_ref<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>) - -> ty::TraitRef<'tcx> { + fn read_trait_ref<'b>(&mut self, dcx: &DecodeContext<'b, 'tcx>) + -> ty::TraitRef<'tcx> { self.read_ty_encoded(dcx, |decoder| decoder.parse_trait_ref()) } - fn read_poly_trait_ref<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>) - -> ty::PolyTraitRef<'tcx> { + fn read_poly_trait_ref<'b>(&mut self, dcx: &DecodeContext<'b, 'tcx>) + -> ty::PolyTraitRef<'tcx> { ty::Binder(self.read_ty_encoded(dcx, |decoder| decoder.parse_trait_ref())) } - fn read_predicate<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>) - -> ty::Predicate<'tcx> + fn read_predicate<'b>(&mut self, dcx: &DecodeContext<'b, 'tcx>) + -> ty::Predicate<'tcx> { self.read_ty_encoded(dcx, |decoder| decoder.parse_predicate()) } - fn read_substs<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>) - -> &'tcx Substs<'tcx> { + fn read_substs<'b>(&mut self, dcx: &DecodeContext<'b, 'tcx>) + -> &'tcx Substs<'tcx> { self.read_opaque(|_, doc| { Ok(tydecode::TyDecoder::with_doc(dcx.tcx, dcx.cdata.cnum, doc, &mut |d| convert_def_id(dcx, d)) .parse_substs()) }).unwrap() } - fn read_upvar_capture<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>) - -> ty::UpvarCapture<'tcx> { + fn read_upvar_capture<'b>(&mut self, dcx: &DecodeContext<'b, 'tcx>) + -> ty::UpvarCapture<'tcx> { self.read_enum("UpvarCapture", |this| { let variants = ["ByValue", "ByRef"]; this.read_enum_variant(&variants, |this, i| { @@ -967,8 +965,8 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> { }) }).unwrap() } - fn read_auto_adjustment<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>) - -> adjustment::AutoAdjustment<'tcx> { + fn read_auto_adjustment<'b>(&mut self, dcx: &DecodeContext<'b, 'tcx>) + -> adjustment::AutoAdjustment<'tcx> { self.read_enum("AutoAdjustment", |this| { let variants = ["AdjustReifyFnPointer", "AdjustUnsafeFnPointer", "AdjustMutToConstPointer", "AdjustDerefRef", @@ -998,8 +996,8 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> { }).unwrap() } - fn read_auto_deref_ref<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>) - -> adjustment::AutoDerefRef<'tcx> { + fn read_auto_deref_ref<'b>(&mut self, dcx: &DecodeContext<'b, 'tcx>) + -> adjustment::AutoDerefRef<'tcx> { self.read_struct("AutoDerefRef", 2, |this| { Ok(adjustment::AutoDerefRef { autoderefs: this.read_struct_field("autoderefs", 0, |this| { @@ -1027,8 +1025,8 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> { }).unwrap() } - fn read_autoref<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>) - -> adjustment::AutoRef<'tcx> { + fn read_autoref<'b>(&mut self, dcx: &DecodeContext<'b, 'tcx>) + -> adjustment::AutoRef<'tcx> { self.read_enum("AutoRef", |this| { let variants = ["AutoPtr", "AutoUnsafe"]; this.read_enum_variant(&variants, |this, i| { @@ -1057,8 +1055,8 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> { }).unwrap() } - fn read_cast_kind<'b, 'c>(&mut self, _dcx: &DecodeContext<'b, 'c, 'tcx>) - -> cast::CastKind + fn read_cast_kind<'b>(&mut self, _dcx: &DecodeContext<'b, 'tcx>) + -> cast::CastKind { Decodable::decode(self).unwrap() } From 78ace66b6a8833b709270584491a5ed8beb51bea Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Mon, 29 Aug 2016 05:03:55 +0300 Subject: [PATCH 04/39] rustc_metadata: remove extension traits from astencode. --- src/librustc_metadata/astencode.rs | 185 ++--------------------------- 1 file changed, 7 insertions(+), 178 deletions(-) diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs index 4469a797eed9b..ece4e8b109745 100644 --- a/src/librustc_metadata/astencode.rs +++ b/src/librustc_metadata/astencode.rs @@ -44,12 +44,10 @@ use syntax_pos; use std::cell::Cell; use std::io::SeekFrom; use std::io::prelude::*; -use std::fmt::Debug; use rbml::reader; use rbml::writer::Encoder; use rbml; -use rustc_serialize as serialize; use rustc_serialize::{Decodable, Decoder, DecoderHelpers}; use rustc_serialize::{Encodable, EncoderHelpers}; @@ -234,40 +232,6 @@ impl tr for syntax_pos::Span { } } -trait def_id_encoder_helpers { - fn emit_def_id(&mut self, did: DefId); -} - -impl def_id_encoder_helpers for S - where ::Error: Debug -{ - fn emit_def_id(&mut self, did: DefId) { - did.encode(self).unwrap() - } -} - -trait def_id_decoder_helpers { - fn read_def_id(&mut self, dcx: &DecodeContext) -> DefId; - fn read_def_id_nodcx(&mut self, - cdata: &cstore::CrateMetadata) -> DefId; -} - -impl def_id_decoder_helpers for D - where ::Error: Debug -{ - fn read_def_id(&mut self, dcx: &DecodeContext) -> DefId { - let did: DefId = Decodable::decode(self).unwrap(); - did.tr(dcx) - } - - fn read_def_id_nodcx(&mut self, - cdata: &cstore::CrateMetadata) - -> DefId { - let did: DefId = Decodable::decode(self).unwrap(); - decoder::translate_def_id(cdata, did) - } -} - // ______________________________________________________________________ // Encoding and decoding the AST itself // @@ -430,23 +394,12 @@ fn encode_freevar_entry(rbml_w: &mut Encoder, fv: &hir::Freevar) { (*fv).encode(rbml_w).unwrap(); } -trait rbml_decoder_helper { - fn read_freevar_entry(&mut self, dcx: &DecodeContext) - -> hir::Freevar; - fn read_capture_mode(&mut self) -> hir::CaptureClause; -} - -impl<'a> rbml_decoder_helper for reader::Decoder<'a> { +impl<'a> reader::Decoder<'a> { fn read_freevar_entry(&mut self, dcx: &DecodeContext) -> hir::Freevar { let fv: hir::Freevar = Decodable::decode(self).unwrap(); fv.tr(dcx) } - - fn read_capture_mode(&mut self) -> hir::CaptureClause { - let cm: hir::CaptureClause = Decodable::decode(self).unwrap(); - cm - } } impl tr for hir::Freevar { @@ -461,11 +414,6 @@ impl tr for hir::Freevar { // ______________________________________________________________________ // Encoding and decoding of MethodCallee -trait read_method_callee_helper<'tcx> { - fn read_method_callee<'a>(&mut self, dcx: &DecodeContext<'a, 'tcx>) - -> (u32, ty::MethodCallee<'tcx>); -} - fn encode_method_callee<'a, 'tcx>(ecx: &e::EncodeContext<'a, 'tcx>, rbml_w: &mut Encoder, autoderef: u32, @@ -477,7 +425,7 @@ fn encode_method_callee<'a, 'tcx>(ecx: &e::EncodeContext<'a, 'tcx>, autoderef.encode(rbml_w) }); rbml_w.emit_struct_field("def_id", 1, |rbml_w| { - Ok(rbml_w.emit_def_id(method.def_id)) + method.def_id.encode(rbml_w) }); rbml_w.emit_struct_field("ty", 2, |rbml_w| { Ok(rbml_w.emit_ty(ecx, method.ty)) @@ -488,7 +436,7 @@ fn encode_method_callee<'a, 'tcx>(ecx: &e::EncodeContext<'a, 'tcx>, }).unwrap(); } -impl<'a, 'tcx> read_method_callee_helper<'tcx> for reader::Decoder<'a> { +impl<'a, 'tcx> reader::Decoder<'a> { fn read_method_callee<'b>(&mut self, dcx: &DecodeContext<'b, 'tcx>) -> (u32, ty::MethodCallee<'tcx>) { @@ -497,7 +445,7 @@ impl<'a, 'tcx> read_method_callee_helper<'tcx> for reader::Decoder<'a> { Decodable::decode).unwrap(); Ok((autoderef, ty::MethodCallee { def_id: this.read_struct_field("def_id", 1, |this| { - Ok(this.read_def_id(dcx)) + DefId::decode(this).map(|d| d.tr(dcx)) }).unwrap(), ty: this.read_struct_field("ty", 2, |this| { Ok(this.read_ty(dcx)) @@ -517,21 +465,7 @@ pub fn encode_cast_kind(ebml_w: &mut Encoder, kind: cast::CastKind) { // ______________________________________________________________________ // Encoding and decoding the side tables -trait rbml_writer_helpers<'tcx> { - fn emit_region(&mut self, ecx: &e::EncodeContext, r: &'tcx ty::Region); - fn emit_ty<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>, ty: Ty<'tcx>); - fn emit_substs<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>, - substs: &Substs<'tcx>); - fn emit_upvar_capture(&mut self, ecx: &e::EncodeContext, capture: &ty::UpvarCapture); - fn emit_auto_adjustment<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>, - adj: &adjustment::AutoAdjustment<'tcx>); - fn emit_autoref<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>, - autoref: &adjustment::AutoRef<'tcx>); - fn emit_auto_deref_ref<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>, - auto_deref_ref: &adjustment::AutoDerefRef<'tcx>); -} - -impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> { +impl<'a, 'tcx> Encoder<'a> { fn emit_region(&mut self, ecx: &e::EncodeContext, r: &'tcx ty::Region) { self.emit_opaque(|this| Ok(tyencode::enc_region(&mut this.cursor, &ecx.ty_str_ctxt(), @@ -661,12 +595,7 @@ impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> { } } -trait write_tag_and_id { - fn tag(&mut self, tag_id: c::astencode_tag, f: F) where F: FnOnce(&mut Self); - fn id(&mut self, id: ast::NodeId); -} - -impl<'a> write_tag_and_id for Encoder<'a> { +impl<'a> Encoder<'a> { fn tag(&mut self, tag_id: c::astencode_tag, f: F) where @@ -808,87 +737,7 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext, } } -trait doc_decoder_helpers: Sized { - fn as_int(&self) -> isize; - fn opt_child(&self, tag: c::astencode_tag) -> Option; -} - -impl<'a> doc_decoder_helpers for rbml::Doc<'a> { - fn as_int(&self) -> isize { reader::doc_as_u64(*self) as isize } - fn opt_child(&self, tag: c::astencode_tag) -> Option> { - reader::maybe_get_doc(*self, tag as usize) - } -} - -trait rbml_decoder_decoder_helpers<'tcx> { - fn read_ty_encoded<'a, F, R>(&mut self, dcx: &DecodeContext<'a, 'tcx>, f: F) -> R - where F: for<'x> FnOnce(&mut tydecode::TyDecoder<'x, 'tcx>) -> R; - - fn read_region<'a>(&mut self, dcx: &DecodeContext<'a, 'tcx>) -> &'tcx ty::Region; - fn read_ty<'a>(&mut self, dcx: &DecodeContext<'a, 'tcx>) -> Ty<'tcx>; - fn read_tys<'a>(&mut self, dcx: &DecodeContext<'a, 'tcx>) -> Vec>; - fn read_trait_ref<'a>(&mut self, dcx: &DecodeContext<'a, 'tcx>) - -> ty::TraitRef<'tcx>; - fn read_poly_trait_ref<'a>(&mut self, dcx: &DecodeContext<'a, 'tcx>) - -> ty::PolyTraitRef<'tcx>; - fn read_predicate<'a>(&mut self, dcx: &DecodeContext<'a, 'tcx>) - -> ty::Predicate<'tcx>; - fn read_substs<'a>(&mut self, dcx: &DecodeContext<'a, 'tcx>) - -> &'tcx Substs<'tcx>; - fn read_upvar_capture<'a>(&mut self, dcx: &DecodeContext<'a, 'tcx>) - -> ty::UpvarCapture<'tcx>; - fn read_auto_adjustment<'a>(&mut self, dcx: &DecodeContext<'a, 'tcx>) - -> adjustment::AutoAdjustment<'tcx>; - fn read_cast_kind<'a>(&mut self, dcx: &DecodeContext<'a, 'tcx>) - -> cast::CastKind; - fn read_auto_deref_ref<'a>(&mut self, dcx: &DecodeContext<'a, 'tcx>) - -> adjustment::AutoDerefRef<'tcx>; - fn read_autoref<'a>(&mut self, dcx: &DecodeContext<'a, 'tcx>) - -> adjustment::AutoRef<'tcx>; - - // Versions of the type reading functions that don't need the full - // DecodeContext. - fn read_ty_nodcx<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>, - cdata: &cstore::CrateMetadata) -> Ty<'tcx>; - fn read_tys_nodcx<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>, - cdata: &cstore::CrateMetadata) -> Vec>; - fn read_substs_nodcx<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>, - cdata: &cstore::CrateMetadata) - -> &'tcx Substs<'tcx>; -} - -impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> { - fn read_ty_nodcx<'b>(&mut self, tcx: TyCtxt<'b, 'tcx, 'tcx>, - cdata: &cstore::CrateMetadata) - -> Ty<'tcx> { - self.read_opaque(|_, doc| { - Ok( - tydecode::TyDecoder::with_doc(tcx, cdata.cnum, doc, - &mut |id| decoder::translate_def_id(cdata, id)) - .parse_ty()) - }).unwrap() - } - - fn read_tys_nodcx<'b>(&mut self, tcx: TyCtxt<'b, 'tcx, 'tcx>, - cdata: &cstore::CrateMetadata) -> Vec> { - self.read_to_vec(|this| Ok(this.read_ty_nodcx(tcx, cdata)) ) - .unwrap() - .into_iter() - .collect() - } - - fn read_substs_nodcx<'b>(&mut self, tcx: TyCtxt<'b, 'tcx, 'tcx>, - cdata: &cstore::CrateMetadata) - -> &'tcx Substs<'tcx> - { - self.read_opaque(|_, doc| { - Ok( - tydecode::TyDecoder::with_doc(tcx, cdata.cnum, doc, - &mut |id| decoder::translate_def_id(cdata, id)) - .parse_substs()) - }).unwrap() - } - +impl<'a, 'tcx> reader::Decoder<'a> { fn read_ty_encoded<'b, F, R>(&mut self, dcx: &DecodeContext<'b, 'tcx>, op: F) -> R where F: for<'x> FnOnce(&mut tydecode::TyDecoder<'x,'tcx>) -> R { @@ -919,26 +768,6 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> { return self.read_ty_encoded(dcx, |decoder| decoder.parse_ty()); } - fn read_tys<'b>(&mut self, dcx: &DecodeContext<'b, 'tcx>) -> Vec> { - self.read_to_vec(|this| Ok(this.read_ty(dcx))).unwrap().into_iter().collect() - } - - fn read_trait_ref<'b>(&mut self, dcx: &DecodeContext<'b, 'tcx>) - -> ty::TraitRef<'tcx> { - self.read_ty_encoded(dcx, |decoder| decoder.parse_trait_ref()) - } - - fn read_poly_trait_ref<'b>(&mut self, dcx: &DecodeContext<'b, 'tcx>) - -> ty::PolyTraitRef<'tcx> { - ty::Binder(self.read_ty_encoded(dcx, |decoder| decoder.parse_trait_ref())) - } - - fn read_predicate<'b>(&mut self, dcx: &DecodeContext<'b, 'tcx>) - -> ty::Predicate<'tcx> - { - self.read_ty_encoded(dcx, |decoder| decoder.parse_predicate()) - } - fn read_substs<'b>(&mut self, dcx: &DecodeContext<'b, 'tcx>) -> &'tcx Substs<'tcx> { self.read_opaque(|_, doc| { From 7b073343db09aa51c6ff181aa721d4d022aa6d6f Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Mon, 29 Aug 2016 05:12:03 +0300 Subject: [PATCH 05/39] rustc_metadata: remove astencode tests. --- src/librustc/hir/lowering.rs | 32 ++----- src/librustc_metadata/astencode.rs | 138 --------------------------- src/librustc_metadata/rbml/writer.rs | 25 ----- src/librustc_resolve/lib.rs | 4 +- 4 files changed, 12 insertions(+), 187 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 80e034721d63f..f7c3eebdc2981 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -81,21 +81,7 @@ pub trait Resolver { // We must keep the set of definitions up to date as we add nodes that weren't in the AST. // This should only return `None` during testing. - fn definitions(&mut self) -> Option<&mut Definitions>; -} - -pub struct DummyResolver; -impl Resolver for DummyResolver { - fn resolve_generated_global_path(&mut self, _path: &hir::Path, _is_value: bool) -> Def { - Def::Err - } - fn get_resolution(&mut self, _id: NodeId) -> Option { - None - } - fn record_resolution(&mut self, _id: NodeId, _def: Def) {} - fn definitions(&mut self) -> Option<&mut Definitions> { - None - } + fn definitions(&mut self) -> &mut Definitions; } pub fn lower_crate(sess: &Session, @@ -177,9 +163,9 @@ impl<'a> LoweringContext<'a> { where F: FnOnce(&mut LoweringContext) -> T { let old_def = self.parent_def; - self.parent_def = match self.resolver.definitions() { - Some(defs) => Some(defs.opt_def_index(parent_id).unwrap()), - None => old_def, + self.parent_def = { + let defs = self.resolver.definitions(); + Some(defs.opt_def_index(parent_id).unwrap()) }; let result = f(self); @@ -1719,9 +1705,10 @@ impl<'a> LoweringContext<'a> { let expr_path = hir::ExprPath(None, self.path_ident(span, id)); let expr = self.expr(span, expr_path, ThinVec::new()); - let def = self.resolver.definitions().map(|defs| { + let def = { + let defs = self.resolver.definitions(); Def::Local(defs.local_def_id(binding), binding) - }).unwrap_or(Def::Err); + }; self.resolver.record_resolution(expr.id, def); expr @@ -1869,11 +1856,12 @@ impl<'a> LoweringContext<'a> { let pat = self.pat(span, pat_ident); let parent_def = self.parent_def; - let def = self.resolver.definitions().map(|defs| { + let def = { + let defs = self.resolver.definitions(); let def_path_data = DefPathData::Binding(name.as_str()); let def_index = defs.create_def_with_parent(parent_def, pat.id, def_path_data); Def::Local(DefId::local(def_index), pat.id) - }).unwrap_or(Def::Err); + }; self.resolver.record_resolution(pat.id, def); pat diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs index ece4e8b109745..b7781ef620fa5 100644 --- a/src/librustc_metadata/astencode.rs +++ b/src/librustc_metadata/astencode.rs @@ -51,11 +51,6 @@ use rbml; use rustc_serialize::{Decodable, Decoder, DecoderHelpers}; use rustc_serialize::{Encodable, EncoderHelpers}; -#[cfg(test)] use std::io::Cursor; -#[cfg(test)] use syntax::parse; -#[cfg(test)] use rustc::hir::print as pprust; -#[cfg(test)] use rustc::hir::lowering::{LoweringContext, DummyResolver}; - struct DecodeContext<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, cdata: &'a cstore::CrateMetadata, @@ -1068,136 +1063,3 @@ fn inlined_item_id_range(ii: &InlinedItem) -> IdRange { ii.visit(&mut visitor); visitor.result() } - -// ______________________________________________________________________ -// Testing of astencode_gen - -#[cfg(test)] -fn encode_item_ast(rbml_w: &mut Encoder, item: &hir::Item) { - rbml_w.start_tag(c::tag_tree as usize); - (*item).encode(rbml_w); - rbml_w.end_tag(); -} - -#[cfg(test)] -fn decode_item_ast(item_doc: rbml::Doc) -> hir::Item { - let chi_doc = item_doc.get(c::tag_tree as usize); - let mut d = reader::Decoder::new(chi_doc); - Decodable::decode(&mut d).unwrap() -} - -#[cfg(test)] -trait FakeExtCtxt { - fn call_site(&self) -> syntax_pos::Span; - fn cfg(&self) -> ast::CrateConfig; - fn ident_of(&self, st: &str) -> ast::Ident; - fn name_of(&self, st: &str) -> ast::Name; - fn parse_sess(&self) -> &parse::ParseSess; -} - -#[cfg(test)] -impl FakeExtCtxt for parse::ParseSess { - fn call_site(&self) -> syntax_pos::Span { - syntax_pos::Span { - lo: syntax_pos::BytePos(0), - hi: syntax_pos::BytePos(0), - expn_id: syntax_pos::NO_EXPANSION, - } - } - fn cfg(&self) -> ast::CrateConfig { Vec::new() } - fn ident_of(&self, st: &str) -> ast::Ident { - parse::token::str_to_ident(st) - } - fn name_of(&self, st: &str) -> ast::Name { - parse::token::intern(st) - } - fn parse_sess(&self) -> &parse::ParseSess { self } -} - -#[cfg(test)] -fn mk_ctxt() -> parse::ParseSess { - parse::ParseSess::new() -} - -#[cfg(test)] -fn with_testing_context T>(f: F) -> T { - let mut resolver = DummyResolver; - let mut lcx = LoweringContext::testing_context(&mut resolver); - f(&mut lcx) -} - -#[cfg(test)] -fn roundtrip(in_item: hir::Item) { - let mut wr = Cursor::new(Vec::new()); - encode_item_ast(&mut Encoder::new(&mut wr), &in_item); - let rbml_doc = rbml::Doc::new(wr.get_ref()); - let out_item = decode_item_ast(rbml_doc); - - assert!(in_item == out_item); -} - -#[test] -fn test_basic() { - let cx = mk_ctxt(); - with_testing_context(|lcx| { - roundtrip(lcx.lower_item("e_item!(&cx, - fn foo() {} - ).unwrap())); - }); -} - -#[test] -fn test_smalltalk() { - let cx = mk_ctxt(); - with_testing_context(|lcx| { - roundtrip(lcx.lower_item("e_item!(&cx, - fn foo() -> isize { 3 + 4 } // first smalltalk program ever executed. - ).unwrap())); - }); -} - -#[test] -fn test_more() { - let cx = mk_ctxt(); - with_testing_context(|lcx| { - roundtrip(lcx.lower_item("e_item!(&cx, - fn foo(x: usize, y: usize) -> usize { - let z = x + y; - return z; - } - ).unwrap())); - }); -} - -#[test] -fn test_simplification() { - use middle::cstore::LOCAL_CRATE; - use rustc::hir::def_id::CRATE_DEF_INDEX; - - let cx = mk_ctxt(); - let item = quote_item!(&cx, - fn new_int_alist() -> alist { - fn eq_int(a: isize, b: isize) -> bool { a == b } - return alist {eq_fn: eq_int, data: Vec::new()}; - } - ).unwrap(); - let cx = mk_ctxt(); - with_testing_context(|lcx| { - let hir_item = lcx.lower_item(&item); - let def_id = DefId { krate: LOCAL_CRATE, index: CRATE_DEF_INDEX }; // dummy - let item_in = InlinedItemRef::Item(def_id, &hir_item); - let (item_out, _) = simplify_ast(item_in); - let item_exp = InlinedItem::Item(def_id, P(lcx.lower_item("e_item!(&cx, - fn new_int_alist() -> alist { - return alist {eq_fn: eq_int, data: Vec::new()}; - } - ).unwrap()))); - match (item_out, item_exp) { - (InlinedItem::Item(_, item_out), InlinedItem::Item(_, item_exp)) => { - assert!(pprust::item_to_string(&item_out) == - pprust::item_to_string(&item_exp)); - } - _ => bug!() - } - }); -} diff --git a/src/librustc_metadata/rbml/writer.rs b/src/librustc_metadata/rbml/writer.rs index d6f4b0d03f22c..17b3c392edb36 100644 --- a/src/librustc_metadata/rbml/writer.rs +++ b/src/librustc_metadata/rbml/writer.rs @@ -495,28 +495,3 @@ impl<'a> serialize::Encoder for Encoder<'a> { self.end_tag() } } - -#[test] -fn test_option_int() { - use rbml::reader; - use serialize::{Encodable, Decodable}; - use std::io::Cursor; - - fn test_v(v: Option) { - debug!("v == {:?}", v); - let mut wr = Cursor::new(Vec::new()); - { - let mut rbml_w = Encoder::new(&mut wr); - let _ = v.encode(&mut rbml_w); - } - let rbml_doc = reader::Doc::new(wr.get_ref()); - let mut deser = reader::Decoder::new(rbml_doc); - let v1 = Decodable::decode(&mut deser).unwrap(); - debug!("v1 == {:?}", v1); - assert_eq!(v, v1); - } - - test_v(Some(22)); - test_v(None); - test_v(Some(3)); -} diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 912b39cafff36..31893b0873c72 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1151,8 +1151,8 @@ impl<'a> hir::lowering::Resolver for Resolver<'a> { self.def_map.insert(id, PathResolution::new(def)); } - fn definitions(&mut self) -> Option<&mut Definitions> { - Some(&mut self.definitions) + fn definitions(&mut self) -> &mut Definitions { + &mut self.definitions } } From 82197287a204376ac6c1aa102f8af79bd20246cf Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Mon, 29 Aug 2016 08:55:40 +0300 Subject: [PATCH 06/39] rustc_metadata: combine EncodeContext and rbml::writer::Encoder. --- src/librustc_metadata/astencode.rs | 209 ++-- src/librustc_metadata/csearch.rs | 6 +- src/librustc_metadata/decoder.rs | 6 +- src/librustc_metadata/encoder.rs | 1305 ++++++++++++------------ src/librustc_metadata/index_builder.rs | 67 +- src/librustc_metadata/rbml/writer.rs | 64 +- src/librustc_metadata/tyencode.rs | 7 +- 7 files changed, 800 insertions(+), 864 deletions(-) diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs index b7781ef620fa5..3fd4d0cf27272 100644 --- a/src/librustc_metadata/astencode.rs +++ b/src/librustc_metadata/astencode.rs @@ -46,7 +46,6 @@ use std::io::SeekFrom; use std::io::prelude::*; use rbml::reader; -use rbml::writer::Encoder; use rbml; use rustc_serialize::{Decodable, Decoder, DecoderHelpers}; use rustc_serialize::{Encodable, EncoderHelpers}; @@ -67,9 +66,7 @@ trait tr { // ______________________________________________________________________ // Top-level methods. -pub fn encode_inlined_item(ecx: &e::EncodeContext, - rbml_w: &mut Encoder, - ii: InlinedItemRef) { +pub fn encode_inlined_item(ecx: &mut e::EncodeContext, ii: InlinedItemRef) { let id = match ii { InlinedItemRef::Item(_, i) => i.id, InlinedItemRef::TraitItem(_, ti) => ti.id, @@ -77,22 +74,24 @@ pub fn encode_inlined_item(ecx: &e::EncodeContext, }; debug!("> Encoding inlined item: {} ({:?})", ecx.tcx.node_path_str(id), - rbml_w.writer.seek(SeekFrom::Current(0))); + ecx.writer.seek(SeekFrom::Current(0))); // Folding could be avoided with a smarter encoder. let (ii, expected_id_range) = simplify_ast(ii); let id_range = inlined_item_id_range(&ii); assert_eq!(expected_id_range, id_range); - rbml_w.start_tag(c::tag_ast as usize); - id_range.encode(rbml_w); - encode_ast(rbml_w, &ii); - encode_side_tables_for_ii(ecx, rbml_w, &ii); - rbml_w.end_tag(); + ecx.start_tag(c::tag_ast as usize); + id_range.encode(ecx); + ecx.start_tag(c::tag_tree as usize); + ecx.emit_opaque(|this| ii.encode(this)); + ecx.end_tag(); + encode_side_tables_for_ii(ecx, &ii); + ecx.end_tag(); debug!("< Encoded inlined fn: {} ({:?})", ecx.tcx.node_path_str(id), - rbml_w.writer.seek(SeekFrom::Current(0))); + ecx.writer.seek(SeekFrom::Current(0))); } impl<'a, 'b, 'tcx> ast_map::FoldOps for &'a DecodeContext<'b, 'tcx> { @@ -235,12 +234,6 @@ impl tr for syntax_pos::Span { // We also have to adjust the spans: for now we just insert a dummy span, // but eventually we should add entries to the local codemap as required. -fn encode_ast(rbml_w: &mut Encoder, item: &InlinedItem) { - rbml_w.start_tag(c::tag_tree as usize); - rbml_w.emit_opaque(|this| item.encode(this)); - rbml_w.end_tag(); -} - struct NestedItemsDropper { id_range: IdRange } @@ -385,10 +378,6 @@ impl tr for Def { // ______________________________________________________________________ // Encoding and decoding of freevar information -fn encode_freevar_entry(rbml_w: &mut Encoder, fv: &hir::Freevar) { - (*fv).encode(rbml_w).unwrap(); -} - impl<'a> reader::Decoder<'a> { fn read_freevar_entry(&mut self, dcx: &DecodeContext) -> hir::Freevar { @@ -409,26 +398,27 @@ impl tr for hir::Freevar { // ______________________________________________________________________ // Encoding and decoding of MethodCallee -fn encode_method_callee<'a, 'tcx>(ecx: &e::EncodeContext<'a, 'tcx>, - rbml_w: &mut Encoder, - autoderef: u32, - method: &ty::MethodCallee<'tcx>) { - use rustc_serialize::Encoder; +impl<'a, 'tcx> e::EncodeContext<'a, 'tcx> { + fn encode_method_callee(&mut self, + autoderef: u32, + method: &ty::MethodCallee<'tcx>) { + use rustc_serialize::Encoder; - rbml_w.emit_struct("MethodCallee", 4, |rbml_w| { - rbml_w.emit_struct_field("autoderef", 0, |rbml_w| { - autoderef.encode(rbml_w) - }); - rbml_w.emit_struct_field("def_id", 1, |rbml_w| { - method.def_id.encode(rbml_w) - }); - rbml_w.emit_struct_field("ty", 2, |rbml_w| { - Ok(rbml_w.emit_ty(ecx, method.ty)) - }); - rbml_w.emit_struct_field("substs", 3, |rbml_w| { - Ok(rbml_w.emit_substs(ecx, &method.substs)) - }) - }).unwrap(); + self.emit_struct("MethodCallee", 4, |this| { + this.emit_struct_field("autoderef", 0, |this| { + autoderef.encode(this) + }); + this.emit_struct_field("def_id", 1, |this| { + method.def_id.encode(this) + }); + this.emit_struct_field("ty", 2, |this| { + Ok(this.emit_ty(method.ty)) + }); + this.emit_struct_field("substs", 3, |this| { + Ok(this.emit_substs(&method.substs)) + }) + }).unwrap(); + } } impl<'a, 'tcx> reader::Decoder<'a> { @@ -453,27 +443,25 @@ impl<'a, 'tcx> reader::Decoder<'a> { } } -pub fn encode_cast_kind(ebml_w: &mut Encoder, kind: cast::CastKind) { - kind.encode(ebml_w).unwrap(); -} - // ______________________________________________________________________ // Encoding and decoding the side tables -impl<'a, 'tcx> Encoder<'a> { - fn emit_region(&mut self, ecx: &e::EncodeContext, r: &'tcx ty::Region) { +impl<'a, 'tcx> e::EncodeContext<'a, 'tcx> { + fn emit_region(&mut self, r: &'tcx ty::Region) { + let cx = self.ty_str_ctxt(); self.emit_opaque(|this| Ok(tyencode::enc_region(&mut this.cursor, - &ecx.ty_str_ctxt(), + &cx, r))); } - fn emit_ty<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>, ty: Ty<'tcx>) { + fn emit_ty(&mut self, ty: Ty<'tcx>) { + let cx = self.ty_str_ctxt(); self.emit_opaque(|this| Ok(tyencode::enc_ty(&mut this.cursor, - &ecx.ty_str_ctxt(), + &cx, ty))); } - fn emit_upvar_capture(&mut self, ecx: &e::EncodeContext, capture: &ty::UpvarCapture) { + fn emit_upvar_capture(&mut self, capture: &ty::UpvarCapture<'tcx>) { use rustc_serialize::Encoder; self.emit_enum("UpvarCapture", |this| { @@ -486,22 +474,21 @@ impl<'a, 'tcx> Encoder<'a> { this.emit_enum_variant_arg(0, |this| kind.encode(this)); this.emit_enum_variant_arg(1, - |this| Ok(this.emit_region(ecx, region))) + |this| Ok(this.emit_region(region))) }) } } }).unwrap() } - fn emit_substs<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>, - substs: &Substs<'tcx>) { + fn emit_substs(&mut self, substs: &Substs<'tcx>) { + let cx = self.ty_str_ctxt(); self.emit_opaque(|this| Ok(tyencode::enc_substs(&mut this.cursor, - &ecx.ty_str_ctxt(), + &cx, substs))); } - fn emit_auto_adjustment<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>, - adj: &adjustment::AutoAdjustment<'tcx>) { + fn emit_auto_adjustment(&mut self, adj: &adjustment::AutoAdjustment<'tcx>) { use rustc_serialize::Encoder; self.emit_enum("AutoAdjustment", |this| { @@ -525,21 +512,20 @@ impl<'a, 'tcx> Encoder<'a> { adjustment::AdjustDerefRef(ref auto_deref_ref) => { this.emit_enum_variant("AdjustDerefRef", 4, 2, |this| { this.emit_enum_variant_arg(0, - |this| Ok(this.emit_auto_deref_ref(ecx, auto_deref_ref))) + |this| Ok(this.emit_auto_deref_ref(auto_deref_ref))) }) } adjustment::AdjustNeverToAny(ref ty) => { this.emit_enum_variant("AdjustNeverToAny", 5, 1, |this| { - this.emit_enum_variant_arg(0, |this| Ok(this.emit_ty(ecx, ty))) + this.emit_enum_variant_arg(0, |this| Ok(this.emit_ty(ty))) }) } } }); } - fn emit_autoref<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>, - autoref: &adjustment::AutoRef<'tcx>) { + fn emit_autoref(&mut self, autoref: &adjustment::AutoRef<'tcx>) { use rustc_serialize::Encoder; self.emit_enum("AutoRef", |this| { @@ -547,7 +533,7 @@ impl<'a, 'tcx> Encoder<'a> { &adjustment::AutoPtr(r, m) => { this.emit_enum_variant("AutoPtr", 0, 2, |this| { this.emit_enum_variant_arg(0, - |this| Ok(this.emit_region(ecx, r))); + |this| Ok(this.emit_region(r))); this.emit_enum_variant_arg(1, |this| m.encode(this)) }) } @@ -560,8 +546,7 @@ impl<'a, 'tcx> Encoder<'a> { }); } - fn emit_auto_deref_ref<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>, - auto_deref_ref: &adjustment::AutoDerefRef<'tcx>) { + fn emit_auto_deref_ref(&mut self, auto_deref_ref: &adjustment::AutoDerefRef<'tcx>) { use rustc_serialize::Encoder; self.emit_struct("AutoDerefRef", 2, |this| { @@ -571,7 +556,7 @@ impl<'a, 'tcx> Encoder<'a> { this.emit_option(|this| { match auto_deref_ref.autoref { None => this.emit_option_none(), - Some(ref a) => this.emit_option_some(|this| Ok(this.emit_autoref(ecx, a))), + Some(ref a) => this.emit_option_some(|this| Ok(this.emit_autoref(a))), } }) }); @@ -581,20 +566,18 @@ impl<'a, 'tcx> Encoder<'a> { match auto_deref_ref.unsize { None => this.emit_option_none(), Some(target) => this.emit_option_some(|this| { - Ok(this.emit_ty(ecx, target)) + Ok(this.emit_ty(target)) }) } }) }) }); } -} -impl<'a> Encoder<'a> { fn tag(&mut self, tag_id: c::astencode_tag, f: F) where - F: FnOnce(&mut Encoder<'a>), + F: FnOnce(&mut Self), { self.start_tag(tag_id as usize); f(self); @@ -606,68 +589,61 @@ impl<'a> Encoder<'a> { } } -struct SideTableEncodingIdVisitor<'a, 'b:'a, 'c:'a, 'tcx:'c> { - ecx: &'a e::EncodeContext<'c, 'tcx>, - rbml_w: &'a mut Encoder<'b>, +struct SideTableEncodingIdVisitor<'a, 'b:'a, 'tcx:'b> { + ecx: &'a mut e::EncodeContext<'b, 'tcx>, } -impl<'a, 'b, 'c, 'tcx, 'v> Visitor<'v> for - SideTableEncodingIdVisitor<'a, 'b, 'c, 'tcx> { +impl<'a, 'b, 'tcx, 'v> Visitor<'v> for SideTableEncodingIdVisitor<'a, 'b, 'tcx> { fn visit_id(&mut self, id: ast::NodeId) { - encode_side_tables_for_id(self.ecx, self.rbml_w, id) + encode_side_tables_for_id(self.ecx, id) } } -fn encode_side_tables_for_ii(ecx: &e::EncodeContext, - rbml_w: &mut Encoder, - ii: &InlinedItem) { - rbml_w.start_tag(c::tag_table as usize); +fn encode_side_tables_for_ii(ecx: &mut e::EncodeContext, ii: &InlinedItem) { + ecx.start_tag(c::tag_table as usize); ii.visit(&mut SideTableEncodingIdVisitor { - ecx: ecx, - rbml_w: rbml_w + ecx: ecx }); - rbml_w.end_tag(); + ecx.end_tag(); } -fn encode_side_tables_for_id(ecx: &e::EncodeContext, - rbml_w: &mut Encoder, - id: ast::NodeId) { +fn encode_side_tables_for_id(ecx: &mut e::EncodeContext, id: ast::NodeId) { let tcx = ecx.tcx; debug!("Encoding side tables for id {}", id); if let Some(def) = tcx.expect_def_or_none(id) { - rbml_w.tag(c::tag_table_def, |rbml_w| { - rbml_w.id(id); - def.encode(rbml_w).unwrap(); + ecx.tag(c::tag_table_def, |ecx| { + ecx.id(id); + def.encode(ecx).unwrap(); }) } if let Some(ty) = tcx.node_types().get(&id) { - rbml_w.tag(c::tag_table_node_type, |rbml_w| { - rbml_w.id(id); - rbml_w.emit_ty(ecx, *ty); + ecx.tag(c::tag_table_node_type, |ecx| { + ecx.id(id); + ecx.emit_ty(*ty); }) } if let Some(item_substs) = tcx.tables.borrow().item_substs.get(&id) { - rbml_w.tag(c::tag_table_item_subst, |rbml_w| { - rbml_w.id(id); - rbml_w.emit_substs(ecx, &item_substs.substs); + ecx.tag(c::tag_table_item_subst, |ecx| { + ecx.id(id); + ecx.emit_substs(&item_substs.substs); }) } if let Some(fv) = tcx.freevars.borrow().get(&id) { - rbml_w.tag(c::tag_table_freevars, |rbml_w| { - rbml_w.id(id); - rbml_w.emit_from_vec(fv, |rbml_w, fv_entry| { - Ok(encode_freevar_entry(rbml_w, fv_entry)) + ecx.tag(c::tag_table_freevars, |ecx| { + ecx.id(id); + ecx.emit_from_vec(fv, |ecx, fv_entry| { + fv_entry.encode(ecx) }); }); for freevar in fv { - rbml_w.tag(c::tag_table_upvar_capture_map, |rbml_w| { - rbml_w.id(id); + ecx.tag(c::tag_table_upvar_capture_map, |ecx| { + ecx.id(id); let var_id = freevar.def.var_id(); let upvar_id = ty::UpvarId { @@ -680,17 +656,17 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext, .get(&upvar_id) .unwrap() .clone(); - var_id.encode(rbml_w); - rbml_w.emit_upvar_capture(ecx, &upvar_capture); + var_id.encode(ecx); + ecx.emit_upvar_capture(&upvar_capture); }) } } let method_call = ty::MethodCall::expr(id); if let Some(method) = tcx.tables.borrow().method_map.get(&method_call) { - rbml_w.tag(c::tag_table_method_map, |rbml_w| { - rbml_w.id(id); - encode_method_callee(ecx, rbml_w, method_call.autoderef, method) + ecx.tag(c::tag_table_method_map, |ecx| { + ecx.id(id); + ecx.encode_method_callee(method_call.autoderef, method) }) } @@ -700,10 +676,9 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext, for autoderef in 0..adj.autoderefs { let method_call = ty::MethodCall::autoderef(id, autoderef as u32); if let Some(method) = tcx.tables.borrow().method_map.get(&method_call) { - rbml_w.tag(c::tag_table_method_map, |rbml_w| { - rbml_w.id(id); - encode_method_callee(ecx, rbml_w, - method_call.autoderef, method) + ecx.tag(c::tag_table_method_map, |ecx| { + ecx.id(id); + ecx.encode_method_callee(method_call.autoderef, method) }) } } @@ -711,23 +686,23 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext, _ => {} } - rbml_w.tag(c::tag_table_adjustments, |rbml_w| { - rbml_w.id(id); - rbml_w.emit_auto_adjustment(ecx, adjustment); + ecx.tag(c::tag_table_adjustments, |ecx| { + ecx.id(id); + ecx.emit_auto_adjustment(adjustment); }) } if let Some(cast_kind) = tcx.cast_kinds.borrow().get(&id) { - rbml_w.tag(c::tag_table_cast_kinds, |rbml_w| { - rbml_w.id(id); - encode_cast_kind(rbml_w, *cast_kind) + ecx.tag(c::tag_table_cast_kinds, |ecx| { + ecx.id(id); + cast_kind.encode(ecx).unwrap() }) } if let Some(qualif) = tcx.const_qualif_map.borrow().get(&id) { - rbml_w.tag(c::tag_table_const_qualif, |rbml_w| { - rbml_w.id(id); - qualif.encode(rbml_w).unwrap() + ecx.tag(c::tag_table_const_qualif, |ecx| { + ecx.id(id); + qualif.encode(ecx).unwrap() }) } } diff --git a/src/librustc_metadata/csearch.rs b/src/librustc_metadata/csearch.rs index 21cf3240321bf..c37b2de751f96 100644 --- a/src/librustc_metadata/csearch.rs +++ b/src/librustc_metadata/csearch.rs @@ -13,6 +13,7 @@ use common; use decoder; use encoder; use loader; +use rbml; use middle::cstore::{InlinedItem, CrateStore, CrateSource, ChildItem, ExternCrate, DefLike}; use middle::cstore::{NativeLibraryKind, LinkMeta, LinkagePreference}; @@ -707,15 +708,16 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { mir_map: &MirMap<'tcx>, krate: &hir::Crate) -> Vec { + let type_abbrevs = RefCell::new(FnvHashMap()); let ecx = encoder::EncodeContext { - diag: tcx.sess.diagnostic(), + rbml_w: rbml::writer::Encoder::new(), tcx: tcx, reexports: reexports, link_meta: link_meta, cstore: self, reachable: reachable, mir_map: mir_map, - type_abbrevs: RefCell::new(FnvHashMap()), + type_abbrevs: &type_abbrevs, }; encoder::encode_metadata(ecx, krate) diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 624bffb7e0369..ecddab0d0609e 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -812,10 +812,8 @@ pub fn maybe_get_item_mir<'a, 'tcx>(cdata: Cmd, }; let mut decoder = reader::Decoder::new(mir_doc); - let mut mir = decoder.read_opaque(|opaque_decoder, _| { - tls::enter_decoding_context(&dcx, opaque_decoder, |_, opaque_decoder| { - Decodable::decode(opaque_decoder) - }) + let mut mir = tls::enter_decoding_context(&dcx, |_| { + Decodable::decode(&mut decoder) }).unwrap(); assert!(decoder.position() == mir_doc.end); diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index e228bf7430261..4bc8caf037ae2 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -21,7 +21,7 @@ use def_key; use tyencode; use index::{self, IndexData}; -use middle::cstore::{InlinedItemRef, LinkMeta, tls}; +use middle::cstore::{InlinedItemRef, LinkMeta}; use rustc::hir::def; use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId}; use middle::dependency_format::Linkage; @@ -38,14 +38,14 @@ use rustc_serialize::Encodable; use std::cell::RefCell; use std::io::prelude::*; use std::io::{Cursor, SeekFrom}; +use std::ops::{Deref, DerefMut}; use std::rc::Rc; use std::u32; use syntax::ast::{self, NodeId, Name, CRATE_NODE_ID, CrateNum}; use syntax::attr; -use errors::Handler; use syntax; use syntax_pos::BytePos; -use rbml::writer::Encoder; +use rbml; use rustc::hir::{self, PatKind}; use rustc::hir::intravisit::Visitor; @@ -55,61 +55,65 @@ use rustc::hir::map::DefKey; use super::index_builder::{FromId, IndexBuilder, ItemContentBuilder, Untracked, XRef}; pub struct EncodeContext<'a, 'tcx: 'a> { - pub diag: &'a Handler, + pub rbml_w: rbml::writer::Encoder, pub tcx: TyCtxt<'a, 'tcx, 'tcx>, pub reexports: &'a def::ExportMap, pub link_meta: &'a LinkMeta, pub cstore: &'a cstore::CStore, - pub type_abbrevs: tyencode::abbrev_map<'tcx>, + pub type_abbrevs: &'a tyencode::abbrev_map<'tcx>, pub reachable: &'a NodeSet, pub mir_map: &'a MirMap<'tcx>, } -impl<'a, 'tcx> EncodeContext<'a,'tcx> { - fn local_id(&self, def_id: DefId) -> NodeId { - self.tcx.map.as_local_node_id(def_id).unwrap() +impl<'a, 'tcx> Deref for EncodeContext<'a, 'tcx> { + type Target = rbml::writer::Encoder; + fn deref(&self) -> &Self::Target { + &self.rbml_w } } -fn encode_name(rbml_w: &mut Encoder, name: Name) { - rbml_w.wr_tagged_str(tag_paths_data_name, &name.as_str()); +impl<'a, 'tcx> DerefMut for EncodeContext<'a, 'tcx> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.rbml_w + } +} + +fn encode_name(ecx: &mut EncodeContext, name: Name) { + ecx.wr_tagged_str(tag_paths_data_name, &name.as_str()); } -fn encode_def_id(rbml_w: &mut Encoder, id: DefId) { - rbml_w.wr_tagged_u64(tag_def_id, def_to_u64(id)); +fn encode_def_id(ecx: &mut EncodeContext, id: DefId) { + ecx.wr_tagged_u64(tag_def_id, def_to_u64(id)); } -fn encode_def_key(rbml_w: &mut Encoder, key: DefKey) { +fn encode_def_key(ecx: &mut EncodeContext, key: DefKey) { let simple_key = def_key::simplify_def_key(key); - rbml_w.start_tag(tag_def_key); - simple_key.encode(rbml_w); - rbml_w.end_tag(); + ecx.start_tag(tag_def_key); + simple_key.encode(ecx); + ecx.end_tag(); } /// For every DefId that we create a metadata item for, we include a /// serialized copy of its DefKey, which allows us to recreate a path. -fn encode_def_id_and_key(ecx: &EncodeContext, - rbml_w: &mut Encoder, - def_id: DefId) -{ - encode_def_id(rbml_w, def_id); +fn encode_def_id_and_key(ecx: &mut EncodeContext, def_id: DefId) { + encode_def_id(ecx, def_id); let def_key = ecx.tcx.map.def_key(def_id); - encode_def_key(rbml_w, def_key); + encode_def_key(ecx, def_key); } -fn encode_trait_ref<'a, 'tcx>(rbml_w: &mut Encoder, - ecx: &EncodeContext<'a, 'tcx>, +fn encode_trait_ref<'a, 'tcx>(ecx: &mut EncodeContext<'a, 'tcx>, trait_ref: ty::TraitRef<'tcx>, tag: usize) { - rbml_w.start_tag(tag); - tyencode::enc_trait_ref(rbml_w.writer, &ecx.ty_str_ctxt(), trait_ref); - rbml_w.mark_stable_position(); - rbml_w.end_tag(); + let cx = ecx.ty_str_ctxt(); + ecx.start_tag(tag); + tyencode::enc_trait_ref(&mut ecx.writer, &cx, trait_ref); + ecx.mark_stable_position(); + ecx.end_tag(); } // Item info table encoding -fn encode_family(rbml_w: &mut Encoder, c: char) { - rbml_w.wr_tagged_u8(tag_items_data_item_family, c as u8); +fn encode_family(ecx: &mut EncodeContext, c: char) { + ecx.wr_tagged_u8(tag_items_data_item_family, c as u8); } pub fn def_to_u64(did: DefId) -> u64 { @@ -121,21 +125,18 @@ pub fn def_to_string(_tcx: TyCtxt, did: DefId) -> String { format!("{}:{}", did.krate, did.index.as_usize()) } -fn encode_item_variances(rbml_w: &mut Encoder, - ecx: &EncodeContext, - id: NodeId) { +fn encode_item_variances(ecx: &mut EncodeContext, id: NodeId) { let v = ecx.tcx.item_variances(ecx.tcx.map.local_def_id(id)); - rbml_w.start_tag(tag_item_variances); - v.encode(rbml_w); - rbml_w.end_tag(); + ecx.start_tag(tag_item_variances); + v.encode(ecx); + ecx.end_tag(); } -impl<'a, 'tcx, 'encoder> ItemContentBuilder<'a, 'tcx, 'encoder> { - fn encode_bounds_and_type_for_item(&mut self, - id: NodeId) { - let ecx = self.ecx(); - self.encode_bounds_and_type(&ecx.tcx.lookup_item_type(ecx.tcx.map.local_def_id(id)), - &ecx.tcx.lookup_predicates(ecx.tcx.map.local_def_id(id))); +impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { + fn encode_bounds_and_type_for_item(&mut self, def_id: DefId) { + let tcx = self.tcx; + self.encode_bounds_and_type(&tcx.lookup_item_type(def_id), + &tcx.lookup_predicates(def_id)); } fn encode_bounds_and_type(&mut self, @@ -146,61 +147,58 @@ impl<'a, 'tcx, 'encoder> ItemContentBuilder<'a, 'tcx, 'encoder> { } } -fn encode_variant_id(rbml_w: &mut Encoder, vid: DefId) { +fn encode_variant_id(ecx: &mut EncodeContext, vid: DefId) { let id = def_to_u64(vid); - rbml_w.wr_tagged_u64(tag_items_data_item_variant, id); - rbml_w.wr_tagged_u64(tag_mod_child, id); + ecx.wr_tagged_u64(tag_items_data_item_variant, id); + ecx.wr_tagged_u64(tag_mod_child, id); } -fn write_closure_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, - rbml_w: &mut Encoder, - closure_type: &ty::ClosureTy<'tcx>) { - tyencode::enc_closure_ty(rbml_w.writer, &ecx.ty_str_ctxt(), closure_type); - rbml_w.mark_stable_position(); +fn write_closure_type<'a, 'tcx>(ecx: &mut EncodeContext<'a, 'tcx>, + closure_type: &ty::ClosureTy<'tcx>) { + let cx = ecx.ty_str_ctxt(); + tyencode::enc_closure_ty(&mut ecx.writer, &cx, closure_type); + ecx.mark_stable_position(); } -impl<'a, 'tcx, 'encoder> ItemContentBuilder<'a, 'tcx, 'encoder> { - fn encode_type(&mut self, - typ: Ty<'tcx>) { - let ecx = self.ecx; - self.rbml_w.start_tag(tag_items_data_item_type); - tyencode::enc_ty(self.rbml_w.writer, &ecx.ty_str_ctxt(), typ); - self.rbml_w.mark_stable_position(); - self.rbml_w.end_tag(); +impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { + fn encode_type(&mut self, typ: Ty<'tcx>) { + let cx = self.ty_str_ctxt(); + self.start_tag(tag_items_data_item_type); + tyencode::enc_ty(&mut self.writer, &cx, typ); + self.mark_stable_position(); + self.end_tag(); } fn encode_disr_val(&mut self, disr_val: ty::Disr) { // convert to u64 so just the number is printed, without any type info - self.rbml_w.wr_tagged_str(tag_disr_val, &disr_val.to_u64_unchecked().to_string()); + self.wr_tagged_str(tag_disr_val, &disr_val.to_u64_unchecked().to_string()); } fn encode_parent_item(&mut self, id: DefId) { - self.rbml_w.wr_tagged_u64(tag_items_data_parent_item, def_to_u64(id)); + self.wr_tagged_u64(tag_items_data_parent_item, def_to_u64(id)); } fn encode_struct_fields(&mut self, variant: ty::VariantDef) { for f in &variant.fields { if variant.kind == ty::VariantKind::Tuple { - self.rbml_w.start_tag(tag_item_unnamed_field); + self.start_tag(tag_item_unnamed_field); } else { - self.rbml_w.start_tag(tag_item_field); - encode_name(self.rbml_w, f.name); + self.start_tag(tag_item_field); + encode_name(self, f.name); } self.encode_struct_field_family(f.vis); - encode_def_id(self.rbml_w, f.did); - self.rbml_w.end_tag(); + encode_def_id(self, f.did); + self.end_tag(); } } } -impl<'a, 'tcx, 'encoder> IndexBuilder<'a, 'tcx, 'encoder> { - fn encode_enum_variant_infos(&mut self, - enum_did: DefId) { +impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { + fn encode_enum_variant_infos(&mut self, enum_did: DefId) { debug!("encode_enum_variant_info(enum_did={:?})", enum_did); - let ecx = self.ecx(); - let def = ecx.tcx.lookup_adt_def(enum_did); + let def = self.tcx.lookup_adt_def(enum_did); self.encode_fields(enum_did); for (i, variant) in def.variants.iter().enumerate() { self.record(variant.did, @@ -210,7 +208,7 @@ impl<'a, 'tcx, 'encoder> IndexBuilder<'a, 'tcx, 'encoder> { } } -impl<'a, 'tcx, 'encoder> ItemContentBuilder<'a, 'tcx, 'encoder> { +impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { /// Encode data for the given variant of the given ADT. The /// index of the variant is untracked: this is ok because we /// will have to lookup the adt-def by its id, and that gives us @@ -219,42 +217,39 @@ impl<'a, 'tcx, 'encoder> ItemContentBuilder<'a, 'tcx, 'encoder> { fn encode_enum_variant_info(&mut self, (enum_did, Untracked(index)): (DefId, Untracked)) { - let ecx = self.ecx; - let def = ecx.tcx.lookup_adt_def(enum_did); + let tcx = self.tcx; + let def = tcx.lookup_adt_def(enum_did); let variant = &def.variants[index]; let vid = variant.did; - let variant_node_id = ecx.local_id(vid); - encode_def_id_and_key(ecx, self.rbml_w, vid); - encode_family(self.rbml_w, match variant.kind { + encode_def_id_and_key(self, vid); + encode_family(self, match variant.kind { ty::VariantKind::Struct => 'V', ty::VariantKind::Tuple => 'v', ty::VariantKind::Unit => 'w', }); - encode_name(self.rbml_w, variant.name); + encode_name(self, variant.name); self.encode_parent_item(enum_did); - let enum_id = ecx.tcx.map.as_local_node_id(enum_did).unwrap(); - let enum_vis = &ecx.tcx.map.expect_item(enum_id).vis; + let enum_id = tcx.map.as_local_node_id(enum_did).unwrap(); + let enum_vis = &tcx.map.expect_item(enum_id).vis; self.encode_visibility(enum_vis); - let attrs = ecx.tcx.get_attrs(vid); - encode_attributes(self.rbml_w, &attrs); + let attrs = tcx.get_attrs(vid); + encode_attributes(self, &attrs); self.encode_repr_attrs(&attrs); - let stab = ecx.tcx.lookup_stability(vid); - let depr = ecx.tcx.lookup_deprecation(vid); - encode_stability(self.rbml_w, stab); - encode_deprecation(self.rbml_w, depr); + let stab = tcx.lookup_stability(vid); + let depr = tcx.lookup_deprecation(vid); + encode_stability(self, stab); + encode_deprecation(self, depr); self.encode_struct_fields(variant); self.encode_disr_val(variant.disr_val); - self.encode_bounds_and_type_for_item(variant_node_id); + self.encode_bounds_and_type_for_item(vid); } } -fn encode_reexports(ecx: &EncodeContext, - rbml_w: &mut Encoder, - id: NodeId) { +fn encode_reexports(ecx: &mut EncodeContext, id: NodeId) { debug!("(encoding info for module) encoding reexports for {}", id); match ecx.reexports.get(&id) { Some(exports) => { @@ -265,58 +260,58 @@ fn encode_reexports(ecx: &EncodeContext, exp.name, exp.def_id, id); - rbml_w.start_tag(tag_items_data_item_reexport); - rbml_w.wr_tagged_u64(tag_items_data_item_reexport_def_id, - def_to_u64(exp.def_id)); - rbml_w.wr_tagged_str(tag_items_data_item_reexport_name, - &exp.name.as_str()); - rbml_w.end_tag(); + ecx.start_tag(tag_items_data_item_reexport); + ecx.wr_tagged_u64(tag_items_data_item_reexport_def_id, + def_to_u64(exp.def_id)); + ecx.wr_tagged_str(tag_items_data_item_reexport_name, + &exp.name.as_str()); + ecx.end_tag(); } }, None => debug!("(encoding info for module) found no reexports for {}", id), } } -impl<'a, 'tcx, 'encoder> ItemContentBuilder<'a, 'tcx, 'encoder> { +impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { fn encode_info_for_mod(&mut self, FromId(id, (md, attrs, name, vis)): FromId<(&hir::Mod, &[ast::Attribute], Name, &hir::Visibility)>) { - let ecx = self.ecx(); + let tcx = self.tcx; - encode_def_id_and_key(ecx, self.rbml_w, ecx.tcx.map.local_def_id(id)); - encode_family(self.rbml_w, 'm'); - encode_name(self.rbml_w, name); + encode_def_id_and_key(self, tcx.map.local_def_id(id)); + encode_family(self, 'm'); + encode_name(self, name); debug!("(encoding info for module) encoding info for module ID {}", id); // Encode info about all the module children. for item_id in &md.item_ids { - self.rbml_w.wr_tagged_u64(tag_mod_child, - def_to_u64(ecx.tcx.map.local_def_id(item_id.id))); + self.wr_tagged_u64(tag_mod_child, + def_to_u64(tcx.map.local_def_id(item_id.id))); } self.encode_visibility(vis); - let stab = ecx.tcx.lookup_stability(ecx.tcx.map.local_def_id(id)); - let depr = ecx.tcx.lookup_deprecation(ecx.tcx.map.local_def_id(id)); - encode_stability(self.rbml_w, stab); - encode_deprecation(self.rbml_w, depr); + let stab = tcx.lookup_stability(tcx.map.local_def_id(id)); + let depr = tcx.lookup_deprecation(tcx.map.local_def_id(id)); + encode_stability(self, stab); + encode_deprecation(self, depr); // Encode the reexports of this module, if this module is public. if *vis == hir::Public { debug!("(encoding info for module) encoding reexports for {}", id); - encode_reexports(ecx, self.rbml_w, id); + encode_reexports(self, id); } - encode_attributes(self.rbml_w, attrs); + encode_attributes(self, attrs); } fn encode_struct_field_family(&mut self, visibility: ty::Visibility) { - encode_family(self.rbml_w, if visibility.is_public() { 'g' } else { 'N' }); + encode_family(self, if visibility.is_public() { 'g' } else { 'N' }); } fn encode_visibility(&mut self, visibility: T) { let ch = if visibility.is_public() { 'y' } else { 'i' }; - self.rbml_w.wr_tagged_u8(tag_items_data_item_visibility, ch as u8); + self.wr_tagged_u8(tag_items_data_item_visibility, ch as u8); } } @@ -336,43 +331,43 @@ impl HasVisibility for ty::Visibility { } } -fn encode_constness(rbml_w: &mut Encoder, constness: hir::Constness) { - rbml_w.start_tag(tag_items_data_item_constness); +fn encode_constness(ecx: &mut EncodeContext, constness: hir::Constness) { + ecx.start_tag(tag_items_data_item_constness); let ch = match constness { hir::Constness::Const => 'c', hir::Constness::NotConst => 'n', }; - rbml_w.wr_str(&ch.to_string()); - rbml_w.end_tag(); + ecx.wr_str(&ch.to_string()); + ecx.end_tag(); } -fn encode_defaultness(rbml_w: &mut Encoder, defaultness: hir::Defaultness) { +fn encode_defaultness(ecx: &mut EncodeContext, defaultness: hir::Defaultness) { let ch = match defaultness { hir::Defaultness::Default => 'd', hir::Defaultness::Final => 'f', }; - rbml_w.wr_tagged_u8(tag_items_data_item_defaultness, ch as u8); + ecx.wr_tagged_u8(tag_items_data_item_defaultness, ch as u8); } -fn encode_explicit_self(rbml_w: &mut Encoder, +fn encode_explicit_self(ecx: &mut EncodeContext, explicit_self: &ty::ExplicitSelfCategory) { let tag = tag_item_trait_method_explicit_self; // Encode the base self type. match *explicit_self { ty::ExplicitSelfCategory::Static => { - rbml_w.wr_tagged_bytes(tag, &['s' as u8]); + ecx.wr_tagged_bytes(tag, &['s' as u8]); } ty::ExplicitSelfCategory::ByValue => { - rbml_w.wr_tagged_bytes(tag, &['v' as u8]); + ecx.wr_tagged_bytes(tag, &['v' as u8]); } ty::ExplicitSelfCategory::ByBox => { - rbml_w.wr_tagged_bytes(tag, &['~' as u8]); + ecx.wr_tagged_bytes(tag, &['~' as u8]); } ty::ExplicitSelfCategory::ByReference(_, m) => { // FIXME(#4846) encode custom lifetime let ch = encode_mutability(m); - rbml_w.wr_tagged_bytes(tag, &['&' as u8, ch]); + ecx.wr_tagged_bytes(tag, &['&' as u8, ch]); } } @@ -384,14 +379,14 @@ fn encode_explicit_self(rbml_w: &mut Encoder, } } -fn encode_item_sort(rbml_w: &mut Encoder, sort: char) { - rbml_w.wr_tagged_u8(tag_item_trait_item_sort, sort as u8); +fn encode_item_sort(ecx: &mut EncodeContext, sort: char) { + ecx.wr_tagged_u8(tag_item_trait_item_sort, sort as u8); } -impl<'a, 'tcx, 'encoder> IndexBuilder<'a, 'tcx, 'encoder> { +impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { fn encode_fields(&mut self, adt_def_id: DefId) { - let def = self.ecx().tcx.lookup_adt_def(adt_def_id); + let def = self.tcx.lookup_adt_def(adt_def_id); for (variant_index, variant) in def.variants.iter().enumerate() { for (field_index, field) in variant.fields.iter().enumerate() { self.record(field.did, @@ -402,7 +397,7 @@ impl<'a, 'tcx, 'encoder> IndexBuilder<'a, 'tcx, 'encoder> { } } -impl<'a, 'tcx, 'encoder> ItemContentBuilder<'a, 'tcx, 'encoder> { +impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { /// Encode data for the given field of the given variant of the /// given ADT. The indices of the variant/field are untracked: /// this is ok because we will have to lookup the adt-def by its @@ -412,131 +407,120 @@ impl<'a, 'tcx, 'encoder> ItemContentBuilder<'a, 'tcx, 'encoder> { fn encode_field(&mut self, (adt_def_id, Untracked((variant_index, field_index))): (DefId, Untracked<(usize, usize)>)) { - let ecx = self.ecx(); - let def = ecx.tcx.lookup_adt_def(adt_def_id); + let tcx = self.tcx; + let def = tcx.lookup_adt_def(adt_def_id); let variant = &def.variants[variant_index]; let field = &variant.fields[field_index]; let nm = field.name; - let id = ecx.local_id(field.did); - debug!("encode_field: encoding {} {}", nm, id); + debug!("encode_field: encoding {} {:?}", nm, field.did); self.encode_struct_field_family(field.vis); - encode_name(self.rbml_w, nm); - self.encode_bounds_and_type_for_item(id); - encode_def_id_and_key(ecx, self.rbml_w, field.did); + encode_name(self, nm); + self.encode_bounds_and_type_for_item(field.did); + encode_def_id_and_key(self, field.did); - let stab = ecx.tcx.lookup_stability(field.did); - let depr = ecx.tcx.lookup_deprecation(field.did); - encode_stability(self.rbml_w, stab); - encode_deprecation(self.rbml_w, depr); + let stab = tcx.lookup_stability(field.did); + let depr = tcx.lookup_deprecation(field.did); + encode_stability(self, stab); + encode_deprecation(self, depr); } -} -impl<'a, 'tcx, 'encoder> ItemContentBuilder<'a, 'tcx, 'encoder> { fn encode_struct_ctor(&mut self, (struct_def_id, struct_node_id, ctor_node_id): (DefId, ast::NodeId, ast::NodeId)) { - let ecx = self.ecx(); - let def = ecx.tcx.lookup_adt_def(struct_def_id); + let tcx = self.tcx; + let def = tcx.lookup_adt_def(struct_def_id); let variant = def.struct_variant(); - let item = ecx.tcx.map.expect_item(struct_node_id); - let ctor_def_id = ecx.tcx.map.local_def_id(ctor_node_id); - encode_def_id_and_key(ecx, self.rbml_w, ctor_def_id); - encode_family(self.rbml_w, match variant.kind { + let item = tcx.map.expect_item(struct_node_id); + let ctor_def_id = tcx.map.local_def_id(ctor_node_id); + encode_def_id_and_key(self, ctor_def_id); + encode_family(self, match variant.kind { ty::VariantKind::Struct => 'S', ty::VariantKind::Tuple => 's', ty::VariantKind::Unit => 'u', }); - self.encode_bounds_and_type_for_item(ctor_node_id); - encode_name(self.rbml_w, item.name); + self.encode_bounds_and_type_for_item(ctor_def_id); + encode_name(self, item.name); self.encode_parent_item(struct_def_id); - let stab = ecx.tcx.lookup_stability(ctor_def_id); - let depr = ecx.tcx.lookup_deprecation(ctor_def_id); - encode_stability(self.rbml_w, stab); - encode_deprecation(self.rbml_w, depr); + let stab = tcx.lookup_stability(ctor_def_id); + let depr = tcx.lookup_deprecation(ctor_def_id); + encode_stability(self, stab); + encode_deprecation(self, depr); // indicate that this is a tuple struct ctor, because // downstream users will normally want the tuple struct // definition, but without this there is no way for them // to tell that they actually have a ctor rather than a // normal function - self.rbml_w.wr_tagged_bytes(tag_items_data_item_is_tuple_struct_ctor, &[]); + self.wr_tagged_bytes(tag_items_data_item_is_tuple_struct_ctor, &[]); } -} -impl<'a, 'tcx, 'encoder> ItemContentBuilder<'a, 'tcx, 'encoder> { fn encode_generics(&mut self, generics: &ty::Generics<'tcx>, predicates: &ty::GenericPredicates<'tcx>) { - let ecx = self.ecx(); - self.rbml_w.start_tag(tag_item_generics); - tyencode::enc_generics(self.rbml_w.writer, &ecx.ty_str_ctxt(), generics); - self.rbml_w.mark_stable_position(); - self.rbml_w.end_tag(); + let cx = self.ty_str_ctxt(); + self.start_tag(tag_item_generics); + tyencode::enc_generics(&mut self.writer, &cx, generics); + self.mark_stable_position(); + self.end_tag(); self.encode_predicates(predicates, tag_item_predicates); } fn encode_predicates(&mut self, predicates: &ty::GenericPredicates<'tcx>, tag: usize) { - self.rbml_w.start_tag(tag); + self.start_tag(tag); if let Some(def_id) = predicates.parent { - self.rbml_w.wr_tagged_u64(tag_items_data_parent_item, def_to_u64(def_id)); + self.wr_tagged_u64(tag_items_data_parent_item, def_to_u64(def_id)); } for predicate in &predicates.predicates { let xref = self.add_xref(XRef::Predicate(predicate.clone())); - self.rbml_w.wr_tagged_u32(tag_predicate, xref); + self.wr_tagged_u32(tag_predicate, xref); } - self.rbml_w.end_tag(); + self.end_tag(); } - fn encode_method_ty_fields(&mut self, - method_ty: &ty::Method<'tcx>) { - let ecx = self.ecx(); - encode_def_id_and_key(ecx, self.rbml_w, method_ty.def_id); - encode_name(self.rbml_w, method_ty.name); + fn encode_method_ty_fields(&mut self, method_ty: &ty::Method<'tcx>) { + encode_def_id_and_key(self, method_ty.def_id); + encode_name(self, method_ty.name); self.encode_generics(&method_ty.generics, &method_ty.predicates); self.encode_visibility(method_ty.vis); - encode_explicit_self(self.rbml_w, &method_ty.explicit_self); + encode_explicit_self(self, &method_ty.explicit_self); match method_ty.explicit_self { ty::ExplicitSelfCategory::Static => { - encode_family(self.rbml_w, STATIC_METHOD_FAMILY); + encode_family(self, STATIC_METHOD_FAMILY); } - _ => encode_family(self.rbml_w, METHOD_FAMILY) + _ => encode_family(self, METHOD_FAMILY) } } -} -impl<'a, 'tcx, 'encoder> ItemContentBuilder<'a, 'tcx, 'encoder> { fn encode_info_for_trait_item(&mut self, (trait_def_id, item_def_id, trait_item): (DefId, DefId, &hir::TraitItem)) { - let ecx = self.ecx; - let tcx = ecx.tcx; + let tcx = self.tcx; self.encode_parent_item(trait_def_id); let stab = tcx.lookup_stability(item_def_id); let depr = tcx.lookup_deprecation(item_def_id); - encode_stability(self.rbml_w, stab); - encode_deprecation(self.rbml_w, depr); + encode_stability(self, stab); + encode_deprecation(self, depr); let trait_item_type = tcx.impl_or_trait_item(item_def_id); let is_nonstatic_method; match trait_item_type { ty::ConstTraitItem(associated_const) => { - encode_name(self.rbml_w, associated_const.name); - encode_def_id_and_key(ecx, self.rbml_w, associated_const.def_id); + encode_name(self, associated_const.name); + encode_def_id_and_key(self, associated_const.def_id); self.encode_visibility(associated_const.vis); - encode_family(self.rbml_w, 'C'); + encode_family(self, 'C'); - self.encode_bounds_and_type_for_item( - ecx.local_id(associated_const.def_id)); + self.encode_bounds_and_type_for_item(associated_const.def_id); is_nonstatic_method = false; } @@ -547,24 +531,22 @@ impl<'a, 'tcx, 'encoder> ItemContentBuilder<'a, 'tcx, 'encoder> { match method_ty.explicit_self { ty::ExplicitSelfCategory::Static => { - encode_family(self.rbml_w, - STATIC_METHOD_FAMILY); + encode_family(self, STATIC_METHOD_FAMILY); } _ => { - encode_family(self.rbml_w, - METHOD_FAMILY); + encode_family(self, METHOD_FAMILY); } } - self.encode_bounds_and_type_for_item(ecx.local_id(method_def_id)); + self.encode_bounds_and_type_for_item(method_def_id); is_nonstatic_method = method_ty.explicit_self != ty::ExplicitSelfCategory::Static; } ty::TypeTraitItem(associated_type) => { - encode_name(self.rbml_w, associated_type.name); - encode_def_id_and_key(ecx, self.rbml_w, associated_type.def_id); - encode_item_sort(self.rbml_w, 't'); - encode_family(self.rbml_w, 'y'); + encode_name(self, associated_type.name); + encode_def_id_and_key(self, associated_type.def_id); + encode_item_sort(self, 't'); + encode_family(self, 'y'); if let Some(ty) = associated_type.ty { self.encode_type(ty); @@ -574,32 +556,31 @@ impl<'a, 'tcx, 'encoder> ItemContentBuilder<'a, 'tcx, 'encoder> { } } - encode_attributes(self.rbml_w, &trait_item.attrs); + encode_attributes(self, &trait_item.attrs); match trait_item.node { hir::ConstTraitItem(_, ref default) => { if default.is_some() { - encode_item_sort(self.rbml_w, 'C'); + encode_item_sort(self, 'C'); } else { - encode_item_sort(self.rbml_w, 'c'); + encode_item_sort(self, 'c'); } - encode_inlined_item(ecx, self.rbml_w, + encode_inlined_item(self, InlinedItemRef::TraitItem(trait_def_id, trait_item)); - self.encode_mir(trait_item.id); + self.encode_mir(item_def_id); } hir::MethodTraitItem(ref sig, ref body) => { // If this is a static method, we've already // encoded self. if is_nonstatic_method { - self.encode_bounds_and_type_for_item( - ecx.local_id(item_def_id)); + self.encode_bounds_and_type_for_item(item_def_id); } if body.is_some() { - encode_item_sort(self.rbml_w, 'p'); - self.encode_mir(trait_item.id); + encode_item_sort(self, 'p'); + self.encode_mir(item_def_id); } else { - encode_item_sort(self.rbml_w, 'r'); + encode_item_sort(self, 'r'); } self.encode_method_argument_names(&sig.decl); } @@ -611,7 +592,7 @@ impl<'a, 'tcx, 'encoder> ItemContentBuilder<'a, 'tcx, 'encoder> { fn encode_info_for_impl_item(&mut self, (impl_id, impl_item_def_id, ast_item): (NodeId, DefId, Option<&hir::ImplItem>)) { - match self.ecx.tcx.impl_or_trait_item(impl_item_def_id) { + match self.tcx.impl_or_trait_item(impl_item_def_id) { ty::ConstTraitItem(ref associated_const) => { self.encode_info_for_associated_const(&associated_const, impl_id, @@ -635,34 +616,33 @@ impl<'a, 'tcx, 'encoder> ItemContentBuilder<'a, 'tcx, 'encoder> { associated_const: &ty::AssociatedConst, parent_id: NodeId, impl_item_opt: Option<&hir::ImplItem>) { - let ecx = self.ecx(); + let tcx = self.tcx; debug!("encode_info_for_associated_const({:?},{:?})", associated_const.def_id, associated_const.name); - encode_def_id_and_key(ecx, self.rbml_w, associated_const.def_id); - encode_name(self.rbml_w, associated_const.name); + encode_def_id_and_key(self, associated_const.def_id); + encode_name(self, associated_const.name); self.encode_visibility(associated_const.vis); - encode_family(self.rbml_w, 'C'); + encode_family(self, 'C'); - self.encode_parent_item(ecx.tcx.map.local_def_id(parent_id)); - encode_item_sort(self.rbml_w, 'C'); + self.encode_parent_item(tcx.map.local_def_id(parent_id)); + encode_item_sort(self, 'C'); - self.encode_bounds_and_type_for_item(ecx.local_id(associated_const.def_id)); + self.encode_bounds_and_type_for_item(associated_const.def_id); - let stab = ecx.tcx.lookup_stability(associated_const.def_id); - let depr = ecx.tcx.lookup_deprecation(associated_const.def_id); - encode_stability(self.rbml_w, stab); - encode_deprecation(self.rbml_w, depr); + let stab = tcx.lookup_stability(associated_const.def_id); + let depr = tcx.lookup_deprecation(associated_const.def_id); + encode_stability(self, stab); + encode_deprecation(self, depr); if let Some(ii) = impl_item_opt { - encode_attributes(self.rbml_w, &ii.attrs); - encode_defaultness(self.rbml_w, ii.defaultness); - encode_inlined_item(ecx, - self.rbml_w, - InlinedItemRef::ImplItem(ecx.tcx.map.local_def_id(parent_id), + encode_attributes(self, &ii.attrs); + encode_defaultness(self, ii.defaultness); + encode_inlined_item(self, + InlinedItemRef::ImplItem(tcx.map.local_def_id(parent_id), ii)); - self.encode_mir(ii.id); + self.encode_mir(associated_const.def_id); } } @@ -671,41 +651,39 @@ impl<'a, 'tcx, 'encoder> ItemContentBuilder<'a, 'tcx, 'encoder> { is_default_impl: bool, parent_id: NodeId, impl_item_opt: Option<&hir::ImplItem>) { - let ecx = self.ecx(); + let tcx = self.tcx; debug!("encode_info_for_method: {:?} {:?}", m.def_id, m.name); self.encode_method_ty_fields(m); - self.encode_parent_item(ecx.tcx.map.local_def_id(parent_id)); - encode_item_sort(self.rbml_w, 'r'); + self.encode_parent_item(tcx.map.local_def_id(parent_id)); + encode_item_sort(self, 'r'); - let stab = ecx.tcx.lookup_stability(m.def_id); - let depr = ecx.tcx.lookup_deprecation(m.def_id); - encode_stability(self.rbml_w, stab); - encode_deprecation(self.rbml_w, depr); + let stab = tcx.lookup_stability(m.def_id); + let depr = tcx.lookup_deprecation(m.def_id); + encode_stability(self, stab); + encode_deprecation(self, depr); - let m_node_id = ecx.local_id(m.def_id); - self.encode_bounds_and_type_for_item(m_node_id); + self.encode_bounds_and_type_for_item(m.def_id); if let Some(impl_item) = impl_item_opt { if let hir::ImplItemKind::Method(ref sig, _) = impl_item.node { - encode_attributes(self.rbml_w, &impl_item.attrs); - let generics = ecx.tcx.lookup_generics(m.def_id); + encode_attributes(self, &impl_item.attrs); + let generics = tcx.lookup_generics(m.def_id); let types = generics.parent_types as usize + generics.types.len(); let needs_inline = types > 0 || is_default_impl || attr::requests_inline(&impl_item.attrs); if sig.constness == hir::Constness::Const { encode_inlined_item( - ecx, - self.rbml_w, - InlinedItemRef::ImplItem(ecx.tcx.map.local_def_id(parent_id), + self, + InlinedItemRef::ImplItem(tcx.map.local_def_id(parent_id), impl_item)); } if needs_inline || sig.constness == hir::Constness::Const { - self.encode_mir(impl_item.id); + self.encode_mir(m.def_id); } - encode_constness(self.rbml_w, sig.constness); - encode_defaultness(self.rbml_w, impl_item.defaultness); + encode_constness(self, sig.constness); + encode_defaultness(self, impl_item.defaultness); self.encode_method_argument_names(&sig.decl); } } @@ -715,74 +693,65 @@ impl<'a, 'tcx, 'encoder> ItemContentBuilder<'a, 'tcx, 'encoder> { associated_type: &ty::AssociatedType<'tcx>, parent_id: NodeId, impl_item_opt: Option<&hir::ImplItem>) { - let ecx = self.ecx(); + let tcx = self.tcx; debug!("encode_info_for_associated_type({:?},{:?})", associated_type.def_id, associated_type.name); - encode_def_id_and_key(ecx, self.rbml_w, associated_type.def_id); - encode_name(self.rbml_w, associated_type.name); + encode_def_id_and_key(self, associated_type.def_id); + encode_name(self, associated_type.name); self.encode_visibility(associated_type.vis); - encode_family(self.rbml_w, 'y'); - self.encode_parent_item(ecx.tcx.map.local_def_id(parent_id)); - encode_item_sort(self.rbml_w, 't'); + encode_family(self, 'y'); + self.encode_parent_item(tcx.map.local_def_id(parent_id)); + encode_item_sort(self, 't'); - let stab = ecx.tcx.lookup_stability(associated_type.def_id); - let depr = ecx.tcx.lookup_deprecation(associated_type.def_id); - encode_stability(self.rbml_w, stab); - encode_deprecation(self.rbml_w, depr); + let stab = tcx.lookup_stability(associated_type.def_id); + let depr = tcx.lookup_deprecation(associated_type.def_id); + encode_stability(self, stab); + encode_deprecation(self, depr); if let Some(ii) = impl_item_opt { - encode_attributes(self.rbml_w, &ii.attrs); - encode_defaultness(self.rbml_w, ii.defaultness); + encode_attributes(self, &ii.attrs); + encode_defaultness(self, ii.defaultness); } if let Some(ty) = associated_type.ty { self.encode_type(ty); } } -} -impl<'a, 'tcx, 'encoder> ItemContentBuilder<'a, 'tcx, 'encoder> { fn encode_method_argument_names(&mut self, decl: &hir::FnDecl) { - self.rbml_w.start_tag(tag_method_argument_names); + self.start_tag(tag_method_argument_names); for arg in &decl.inputs { let tag = tag_method_argument_name; if let PatKind::Binding(_, ref path1, _) = arg.pat.node { let name = path1.node.as_str(); - self.rbml_w.wr_tagged_bytes(tag, name.as_bytes()); + self.wr_tagged_bytes(tag, name.as_bytes()); } else { - self.rbml_w.wr_tagged_bytes(tag, &[]); + self.wr_tagged_bytes(tag, &[]); } } - self.rbml_w.end_tag(); + self.end_tag(); } fn encode_repr_attrs(&mut self, attrs: &[ast::Attribute]) { - let ecx = self.ecx(); let mut repr_attrs = Vec::new(); for attr in attrs { - repr_attrs.extend(attr::find_repr_attrs(ecx.tcx.sess.diagnostic(), + repr_attrs.extend(attr::find_repr_attrs(self.tcx.sess.diagnostic(), attr)); } - self.rbml_w.start_tag(tag_items_data_item_repr); - repr_attrs.encode(self.rbml_w); - self.rbml_w.end_tag(); - } - - fn encode_mir(&mut self, node_id: NodeId) { - let ecx = self.ecx(); - let def_id = ecx.tcx.map.local_def_id(node_id); - if let Some(mir) = ecx.mir_map.map.get(&def_id) { - self.rbml_w.start_tag(tag_mir as usize); - self.rbml_w.emit_opaque(|opaque_encoder| { - tls::enter_encoding_context(ecx, opaque_encoder, |_, opaque_encoder| { - Encodable::encode(mir, opaque_encoder) - }) - }).unwrap(); - self.rbml_w.end_tag(); + self.start_tag(tag_items_data_item_repr); + repr_attrs.encode(self.ecx); + self.end_tag(); + } + + fn encode_mir(&mut self, def_id: DefId) { + if let Some(mir) = self.mir_map.map.get(&def_id) { + self.start_tag(tag_mir as usize); + mir.encode(self.ecx); + self.end_tag(); } } } @@ -792,75 +761,73 @@ const STATIC_METHOD_FAMILY: char = 'F'; const METHOD_FAMILY: char = 'h'; // Encodes the inherent implementations of a structure, enumeration, or trait. -fn encode_inherent_implementations(ecx: &EncodeContext, - rbml_w: &mut Encoder, +fn encode_inherent_implementations(ecx: &mut EncodeContext, def_id: DefId) { match ecx.tcx.inherent_impls.borrow().get(&def_id) { None => {} Some(implementations) => { for &impl_def_id in implementations.iter() { - rbml_w.start_tag(tag_items_data_item_inherent_impl); - encode_def_id(rbml_w, impl_def_id); - rbml_w.end_tag(); + ecx.start_tag(tag_items_data_item_inherent_impl); + encode_def_id(ecx, impl_def_id); + ecx.end_tag(); } } } } -fn encode_stability(rbml_w: &mut Encoder, stab_opt: Option<&attr::Stability>) { +fn encode_stability(ecx: &mut EncodeContext, stab_opt: Option<&attr::Stability>) { stab_opt.map(|stab| { - rbml_w.start_tag(tag_items_data_item_stability); - stab.encode(rbml_w).unwrap(); - rbml_w.end_tag(); + ecx.start_tag(tag_items_data_item_stability); + stab.encode(ecx).unwrap(); + ecx.end_tag(); }); } -fn encode_deprecation(rbml_w: &mut Encoder, depr_opt: Option) { +fn encode_deprecation(ecx: &mut EncodeContext, depr_opt: Option) { depr_opt.map(|depr| { - rbml_w.start_tag(tag_items_data_item_deprecation); - depr.encode(rbml_w).unwrap(); - rbml_w.end_tag(); + ecx.start_tag(tag_items_data_item_deprecation); + depr.encode(ecx).unwrap(); + ecx.end_tag(); }); } -fn encode_parent_impl(rbml_w: &mut Encoder, parent_opt: Option) { +fn encode_parent_impl(ecx: &mut EncodeContext, parent_opt: Option) { parent_opt.map(|parent| { - rbml_w.wr_tagged_u64(tag_items_data_parent_impl, def_to_u64(parent)); + ecx.wr_tagged_u64(tag_items_data_parent_impl, def_to_u64(parent)); }); } -fn encode_xrefs<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, - rbml_w: &mut Encoder, +fn encode_xrefs<'a, 'tcx>(ecx: &mut EncodeContext<'a, 'tcx>, xrefs: FnvHashMap, u32>) { let mut xref_positions = vec![0; xrefs.len()]; + let cx = ecx.ty_str_ctxt(); // Encode XRefs sorted by their ID let mut sorted_xrefs: Vec<_> = xrefs.into_iter().collect(); sorted_xrefs.sort_by_key(|&(_, id)| id); - rbml_w.start_tag(tag_xref_data); + ecx.start_tag(tag_xref_data); for (xref, id) in sorted_xrefs.into_iter() { - xref_positions[id as usize] = rbml_w.mark_stable_position() as u32; + xref_positions[id as usize] = ecx.mark_stable_position() as u32; match xref { XRef::Predicate(p) => { - tyencode::enc_predicate(rbml_w.writer, &ecx.ty_str_ctxt(), &p) + tyencode::enc_predicate(&mut ecx.writer, &cx, &p) } } } - rbml_w.mark_stable_position(); - rbml_w.end_tag(); + ecx.mark_stable_position(); + ecx.end_tag(); - rbml_w.start_tag(tag_xref_index); - index::write_dense_index(xref_positions, rbml_w.writer); - rbml_w.end_tag(); + ecx.start_tag(tag_xref_index); + index::write_dense_index(xref_positions, &mut ecx.writer); + ecx.end_tag(); } -impl<'a, 'tcx, 'encoder> ItemContentBuilder<'a, 'tcx, 'encoder> { +impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { fn encode_info_for_item(&mut self, (def_id, item): (DefId, &hir::Item)) { - let ecx = self.ecx(); - let tcx = ecx.tcx; + let tcx = self.tcx; debug!("encoding info for item at {}", tcx.sess.codemap().span_to_string(item.span)); @@ -868,122 +835,122 @@ impl<'a, 'tcx, 'encoder> ItemContentBuilder<'a, 'tcx, 'encoder> { let vis = &item.vis; let (stab, depr) = tcx.dep_graph.with_task(DepNode::MetaData(def_id), || { - (tcx.lookup_stability(ecx.tcx.map.local_def_id(item.id)), - tcx.lookup_deprecation(ecx.tcx.map.local_def_id(item.id))) + (tcx.lookup_stability(tcx.map.local_def_id(item.id)), + tcx.lookup_deprecation(tcx.map.local_def_id(item.id))) }); match item.node { hir::ItemStatic(_, m, _) => { - encode_def_id_and_key(ecx, self.rbml_w, def_id); + encode_def_id_and_key(self, def_id); if m == hir::MutMutable { - encode_family(self.rbml_w, 'b'); + encode_family(self, 'b'); } else { - encode_family(self.rbml_w, 'c'); + encode_family(self, 'c'); } - self.encode_bounds_and_type_for_item(item.id); - encode_name(self.rbml_w, item.name); + self.encode_bounds_and_type_for_item(def_id); + encode_name(self, item.name); self.encode_visibility(vis); - encode_stability(self.rbml_w, stab); - encode_deprecation(self.rbml_w, depr); - encode_attributes(self.rbml_w, &item.attrs); + encode_stability(self, stab); + encode_deprecation(self, depr); + encode_attributes(self, &item.attrs); } hir::ItemConst(..) => { - encode_def_id_and_key(ecx, self.rbml_w, def_id); - encode_family(self.rbml_w, 'C'); - self.encode_bounds_and_type_for_item(item.id); - encode_name(self.rbml_w, item.name); - encode_attributes(self.rbml_w, &item.attrs); - encode_inlined_item(ecx, self.rbml_w, InlinedItemRef::Item(def_id, item)); - self.encode_mir(item.id); + encode_def_id_and_key(self, def_id); + encode_family(self, 'C'); + self.encode_bounds_and_type_for_item(def_id); + encode_name(self, item.name); + encode_attributes(self, &item.attrs); + encode_inlined_item(self, InlinedItemRef::Item(def_id, item)); + self.encode_mir(def_id); self.encode_visibility(vis); - encode_stability(self.rbml_w, stab); - encode_deprecation(self.rbml_w, depr); + encode_stability(self, stab); + encode_deprecation(self, depr); } hir::ItemFn(ref decl, _, constness, _, ref generics, _) => { - encode_def_id_and_key(ecx, self.rbml_w, def_id); - encode_family(self.rbml_w, FN_FAMILY); + encode_def_id_and_key(self, def_id); + encode_family(self, FN_FAMILY); let tps_len = generics.ty_params.len(); - self.encode_bounds_and_type_for_item(item.id); - encode_name(self.rbml_w, item.name); - encode_attributes(self.rbml_w, &item.attrs); + self.encode_bounds_and_type_for_item(def_id); + encode_name(self, item.name); + encode_attributes(self, &item.attrs); let needs_inline = tps_len > 0 || attr::requests_inline(&item.attrs); if constness == hir::Constness::Const { - encode_inlined_item(ecx, self.rbml_w, InlinedItemRef::Item(def_id, item)); + encode_inlined_item(self, InlinedItemRef::Item(def_id, item)); } if needs_inline || constness == hir::Constness::Const { - self.encode_mir(item.id); + self.encode_mir(def_id); } - encode_constness(self.rbml_w, constness); + encode_constness(self, constness); self.encode_visibility(vis); - encode_stability(self.rbml_w, stab); - encode_deprecation(self.rbml_w, depr); + encode_stability(self, stab); + encode_deprecation(self, depr); self.encode_method_argument_names(&decl); } hir::ItemMod(ref m) => { self.encode_info_for_mod(FromId(item.id, (m, &item.attrs, item.name, &item.vis))); } hir::ItemForeignMod(ref fm) => { - encode_def_id_and_key(ecx, self.rbml_w, def_id); - encode_family(self.rbml_w, 'n'); - encode_name(self.rbml_w, item.name); + encode_def_id_and_key(self, def_id); + encode_family(self, 'n'); + encode_name(self, item.name); // Encode all the items in self module. for foreign_item in &fm.items { - self.rbml_w.wr_tagged_u64( + self.wr_tagged_u64( tag_mod_child, - def_to_u64(ecx.tcx.map.local_def_id(foreign_item.id))); + def_to_u64(tcx.map.local_def_id(foreign_item.id))); } self.encode_visibility(vis); - encode_stability(self.rbml_w, stab); - encode_deprecation(self.rbml_w, depr); + encode_stability(self, stab); + encode_deprecation(self, depr); } hir::ItemTy(..) => { - encode_def_id_and_key(ecx, self.rbml_w, def_id); - encode_family(self.rbml_w, 'y'); - self.encode_bounds_and_type_for_item(item.id); - encode_name(self.rbml_w, item.name); + encode_def_id_and_key(self, def_id); + encode_family(self, 'y'); + self.encode_bounds_and_type_for_item(def_id); + encode_name(self, item.name); self.encode_visibility(vis); - encode_stability(self.rbml_w, stab); - encode_deprecation(self.rbml_w, depr); + encode_stability(self, stab); + encode_deprecation(self, depr); } hir::ItemEnum(ref enum_definition, _) => { - encode_def_id_and_key(ecx, self.rbml_w, def_id); - encode_family(self.rbml_w, 't'); - encode_item_variances(self.rbml_w, ecx, item.id); - self.encode_bounds_and_type_for_item(item.id); - encode_name(self.rbml_w, item.name); - encode_attributes(self.rbml_w, &item.attrs); + encode_def_id_and_key(self, def_id); + encode_family(self, 't'); + encode_item_variances(self, item.id); + self.encode_bounds_and_type_for_item(def_id); + encode_name(self, item.name); + encode_attributes(self, &item.attrs); self.encode_repr_attrs(&item.attrs); for v in &enum_definition.variants { - encode_variant_id(self.rbml_w, ecx.tcx.map.local_def_id(v.node.data.id())); + encode_variant_id(self, tcx.map.local_def_id(v.node.data.id())); } // Encode inherent implementations for self enumeration. - encode_inherent_implementations(ecx, self.rbml_w, def_id); + encode_inherent_implementations(self, def_id); self.encode_visibility(vis); - encode_stability(self.rbml_w, stab); - encode_deprecation(self.rbml_w, depr); + encode_stability(self, stab); + encode_deprecation(self, depr); } hir::ItemStruct(ref struct_def, _) => { /* Index the class*/ - let def = ecx.tcx.lookup_adt_def(def_id); + let def = tcx.lookup_adt_def(def_id); let variant = def.struct_variant(); /* Now, make an item for the class itself */ - encode_def_id_and_key(ecx, self.rbml_w, def_id); - encode_family(self.rbml_w, match *struct_def { + encode_def_id_and_key(self, def_id); + encode_family(self, match *struct_def { hir::VariantData::Struct(..) => 'S', hir::VariantData::Tuple(..) => 's', hir::VariantData::Unit(..) => 'u', }); - self.encode_bounds_and_type_for_item(item.id); + self.encode_bounds_and_type_for_item(def_id); - encode_item_variances(self.rbml_w, ecx, item.id); - encode_name(self.rbml_w, item.name); - encode_attributes(self.rbml_w, &item.attrs); - encode_stability(self.rbml_w, stab); - encode_deprecation(self.rbml_w, depr); + encode_item_variances(self, item.id); + encode_name(self, item.name); + encode_attributes(self, &item.attrs); + encode_stability(self, stab); + encode_deprecation(self, depr); self.encode_visibility(vis); self.encode_repr_attrs(&item.attrs); @@ -993,27 +960,27 @@ impl<'a, 'tcx, 'encoder> ItemContentBuilder<'a, 'tcx, 'encoder> { self.encode_struct_fields(variant); // Encode inherent implementations for self structure. - encode_inherent_implementations(ecx, self.rbml_w, def_id); + encode_inherent_implementations(self, def_id); if !struct_def.is_struct() { - let ctor_did = ecx.tcx.map.local_def_id(struct_def.id()); - self.rbml_w.wr_tagged_u64(tag_items_data_item_struct_ctor, - def_to_u64(ctor_did)); + let ctor_did = tcx.map.local_def_id(struct_def.id()); + self.wr_tagged_u64(tag_items_data_item_struct_ctor, + def_to_u64(ctor_did)); } } hir::ItemUnion(..) => { - let def = ecx.tcx.lookup_adt_def(def_id); + let def = self.tcx.lookup_adt_def(def_id); let variant = def.struct_variant(); - encode_def_id_and_key(ecx, self.rbml_w, def_id); - encode_family(self.rbml_w, 'U'); - self.encode_bounds_and_type_for_item(item.id); + encode_def_id_and_key(self, def_id); + encode_family(self, 'U'); + self.encode_bounds_and_type_for_item(def_id); - encode_item_variances(self.rbml_w, ecx, item.id); - encode_name(self.rbml_w, item.name); - encode_attributes(self.rbml_w, &item.attrs); - encode_stability(self.rbml_w, stab); - encode_deprecation(self.rbml_w, depr); + encode_item_variances(self, item.id); + encode_name(self, item.name); + encode_attributes(self, &item.attrs); + encode_stability(self, stab); + encode_deprecation(self, depr); self.encode_visibility(vis); self.encode_repr_attrs(&item.attrs); @@ -1022,20 +989,20 @@ impl<'a, 'tcx, 'encoder> ItemContentBuilder<'a, 'tcx, 'encoder> { needs to know*/ self.encode_struct_fields(variant); - encode_inlined_item(ecx, self.rbml_w, InlinedItemRef::Item(def_id, item)); - self.encode_mir(item.id); + encode_inlined_item(self, InlinedItemRef::Item(def_id, item)); + self.encode_mir(def_id); // Encode inherent implementations for self union. - encode_inherent_implementations(ecx, self.rbml_w, def_id); + encode_inherent_implementations(self, def_id); } hir::ItemDefaultImpl(unsafety, _) => { - encode_def_id_and_key(ecx, self.rbml_w, def_id); - encode_family(self.rbml_w, 'd'); - encode_name(self.rbml_w, item.name); - encode_unsafety(self.rbml_w, unsafety); + encode_def_id_and_key(self, def_id); + encode_family(self, 'd'); + encode_name(self, item.name); + encode_unsafety(self, unsafety); - let trait_ref = tcx.impl_trait_ref(ecx.tcx.map.local_def_id(item.id)).unwrap(); - encode_trait_ref(self.rbml_w, ecx, trait_ref, tag_item_trait_ref); + let trait_ref = tcx.impl_trait_ref(tcx.map.local_def_id(item.id)).unwrap(); + encode_trait_ref(self, trait_ref, tag_item_trait_ref); } hir::ItemImpl(unsafety, polarity, ..) => { // We need to encode information about the default methods we @@ -1043,49 +1010,49 @@ impl<'a, 'tcx, 'encoder> ItemContentBuilder<'a, 'tcx, 'encoder> { let impl_items = tcx.impl_items.borrow(); let items = &impl_items[&def_id]; - encode_def_id_and_key(ecx, self.rbml_w, def_id); - encode_family(self.rbml_w, 'i'); - self.encode_bounds_and_type_for_item(item.id); - encode_name(self.rbml_w, item.name); - encode_attributes(self.rbml_w, &item.attrs); - encode_unsafety(self.rbml_w, unsafety); - encode_polarity(self.rbml_w, polarity); + encode_def_id_and_key(self, def_id); + encode_family(self, 'i'); + self.encode_bounds_and_type_for_item(def_id); + encode_name(self, item.name); + encode_attributes(self, &item.attrs); + encode_unsafety(self, unsafety); + encode_polarity(self, polarity); match tcx.custom_coerce_unsized_kinds .borrow() - .get(&ecx.tcx.map.local_def_id(item.id)) + .get(&tcx.map.local_def_id(item.id)) { Some(&kind) => { - self.rbml_w.start_tag(tag_impl_coerce_unsized_kind); - kind.encode(self.rbml_w); - self.rbml_w.end_tag(); + self.start_tag(tag_impl_coerce_unsized_kind); + kind.encode(self.ecx); + self.end_tag(); } None => {} } for &item_def_id in items { - self.rbml_w.start_tag(tag_item_impl_item); + self.start_tag(tag_item_impl_item); match item_def_id { ty::ConstTraitItemId(item_def_id) => { - encode_def_id(self.rbml_w, item_def_id); - encode_item_sort(self.rbml_w, 'C'); + encode_def_id(self, item_def_id); + encode_item_sort(self, 'C'); } ty::MethodTraitItemId(item_def_id) => { - encode_def_id(self.rbml_w, item_def_id); - encode_item_sort(self.rbml_w, 'r'); + encode_def_id(self, item_def_id); + encode_item_sort(self, 'r'); } ty::TypeTraitItemId(item_def_id) => { - encode_def_id(self.rbml_w, item_def_id); - encode_item_sort(self.rbml_w, 't'); + encode_def_id(self, item_def_id); + encode_item_sort(self, 't'); } } - self.rbml_w.end_tag(); + self.end_tag(); } - let did = ecx.tcx.map.local_def_id(item.id); + let did = tcx.map.local_def_id(item.id); if let Some(trait_ref) = tcx.impl_trait_ref(did) { - encode_trait_ref(self.rbml_w, ecx, trait_ref, tag_item_trait_ref); + encode_trait_ref(self, trait_ref, tag_item_trait_ref); let trait_def = tcx.lookup_trait_def(trait_ref.def_id); let parent = trait_def.ancestors(did) @@ -1096,54 +1063,54 @@ impl<'a, 'tcx, 'encoder> ItemContentBuilder<'a, 'tcx, 'encoder> { Some(parent), _ => None, }); - encode_parent_impl(self.rbml_w, parent); + encode_parent_impl(self, parent); } - encode_stability(self.rbml_w, stab); - encode_deprecation(self.rbml_w, depr); + encode_stability(self, stab); + encode_deprecation(self, depr); } hir::ItemTrait(..) => { - encode_def_id_and_key(ecx, self.rbml_w, def_id); - encode_family(self.rbml_w, 'I'); - encode_item_variances(self.rbml_w, ecx, item.id); + encode_def_id_and_key(self, def_id); + encode_family(self, 'I'); + encode_item_variances(self, item.id); let trait_def = tcx.lookup_trait_def(def_id); let trait_predicates = tcx.lookup_predicates(def_id); - encode_unsafety(self.rbml_w, trait_def.unsafety); - encode_paren_sugar(self.rbml_w, trait_def.paren_sugar); - encode_defaulted(self.rbml_w, tcx.trait_has_default_impl(def_id)); - encode_associated_type_names(self.rbml_w, &trait_def.associated_type_names); + encode_unsafety(self, trait_def.unsafety); + encode_paren_sugar(self, trait_def.paren_sugar); + encode_defaulted(self, tcx.trait_has_default_impl(def_id)); + encode_associated_type_names(self, &trait_def.associated_type_names); self.encode_generics(&trait_def.generics, &trait_predicates); self.encode_predicates(&tcx.lookup_super_predicates(def_id), tag_item_super_predicates); - encode_trait_ref(self.rbml_w, ecx, trait_def.trait_ref, tag_item_trait_ref); - encode_name(self.rbml_w, item.name); - encode_attributes(self.rbml_w, &item.attrs); + encode_trait_ref(self, trait_def.trait_ref, tag_item_trait_ref); + encode_name(self, item.name); + encode_attributes(self, &item.attrs); self.encode_visibility(vis); - encode_stability(self.rbml_w, stab); - encode_deprecation(self.rbml_w, depr); + encode_stability(self, stab); + encode_deprecation(self, depr); for &method_def_id in tcx.trait_item_def_ids(def_id).iter() { - self.rbml_w.start_tag(tag_item_trait_item); + self.start_tag(tag_item_trait_item); match method_def_id { ty::ConstTraitItemId(const_def_id) => { - encode_def_id(self.rbml_w, const_def_id); - encode_item_sort(self.rbml_w, 'C'); + encode_def_id(self, const_def_id); + encode_item_sort(self, 'C'); } ty::MethodTraitItemId(method_def_id) => { - encode_def_id(self.rbml_w, method_def_id); - encode_item_sort(self.rbml_w, 'r'); + encode_def_id(self, method_def_id); + encode_item_sort(self, 'r'); } ty::TypeTraitItemId(type_def_id) => { - encode_def_id(self.rbml_w, type_def_id); - encode_item_sort(self.rbml_w, 't'); + encode_def_id(self, type_def_id); + encode_item_sort(self, 't'); } } - self.rbml_w.end_tag(); + self.end_tag(); - self.rbml_w.wr_tagged_u64(tag_mod_child, - def_to_u64(method_def_id.def_id())); + self.wr_tagged_u64(tag_mod_child, + def_to_u64(method_def_id.def_id())); } // Encode inherent implementations for self trait. - encode_inherent_implementations(ecx, self.rbml_w, def_id); + encode_inherent_implementations(self, def_id); } hir::ItemExternCrate(_) | hir::ItemUse(_) => { bug!("cannot encode info for item {:?}", item) @@ -1152,14 +1119,14 @@ impl<'a, 'tcx, 'encoder> ItemContentBuilder<'a, 'tcx, 'encoder> { } } -impl<'a, 'tcx, 'encoder> IndexBuilder<'a, 'tcx, 'encoder> { +impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { /// In some cases, along with the item itself, we also /// encode some sub-items. Usually we want some info from the item /// so it's easier to do that here then to wait until we would encounter /// normally in the visitor walk. fn encode_addl_info_for_item(&mut self, item: &hir::Item) { - let def_id = self.ecx().tcx.map.local_def_id(item.id); + let def_id = self.tcx.map.local_def_id(item.id); match item.node { hir::ItemStatic(..) | hir::ItemConst(..) | @@ -1194,8 +1161,7 @@ impl<'a, 'tcx, 'encoder> IndexBuilder<'a, 'tcx, 'encoder> { def_id: DefId, struct_node_id: ast::NodeId, item: &hir::Item) { - let ecx = self.ecx(); - let def = ecx.tcx.lookup_adt_def(def_id); + let def = self.tcx.lookup_adt_def(def_id); let variant = def.struct_variant(); self.encode_fields(def_id); @@ -1208,7 +1174,7 @@ impl<'a, 'tcx, 'encoder> IndexBuilder<'a, 'tcx, 'encoder> { ty::VariantKind::Tuple | ty::VariantKind::Unit => { // there is a value for structs like `struct // Foo()` and `struct Foo` - let ctor_def_id = ecx.tcx.map.local_def_id(struct_node_id); + let ctor_def_id = self.tcx.map.local_def_id(struct_node_id); self.record(ctor_def_id, ItemContentBuilder::encode_struct_ctor, (def_id, item.id, struct_node_id)); @@ -1224,8 +1190,7 @@ impl<'a, 'tcx, 'encoder> IndexBuilder<'a, 'tcx, 'encoder> { def_id: DefId, impl_id: ast::NodeId, ast_items: &[hir::ImplItem]) { - let ecx = self.ecx(); - let impl_items = ecx.tcx.impl_items.borrow(); + let impl_items = self.tcx.impl_items.borrow(); let items = &impl_items[&def_id]; // Iterate down the trait items, emitting them. We rely on the @@ -1251,7 +1216,7 @@ impl<'a, 'tcx, 'encoder> IndexBuilder<'a, 'tcx, 'encoder> { def_id: DefId, trait_items: &[hir::TraitItem]) { // Now output the trait item info for each trait item. - let tcx = self.ecx().tcx; + let tcx = self.tcx; let r = tcx.trait_item_def_ids(def_id); for (item_def_id, trait_item) in r.iter().zip(trait_items) { let item_def_id = item_def_id.def_id(); @@ -1263,59 +1228,59 @@ impl<'a, 'tcx, 'encoder> IndexBuilder<'a, 'tcx, 'encoder> { } } -impl<'a, 'tcx, 'encoder> ItemContentBuilder<'a, 'tcx, 'encoder> { +impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { fn encode_info_for_foreign_item(&mut self, (def_id, nitem): (DefId, &hir::ForeignItem)) { - let ecx = self.ecx(); + let tcx = self.tcx; - debug!("writing foreign item {}", ecx.tcx.node_path_str(nitem.id)); + debug!("writing foreign item {}", tcx.node_path_str(nitem.id)); - encode_def_id_and_key(ecx, self.rbml_w, def_id); - let parent_id = ecx.tcx.map.get_parent(nitem.id); - self.encode_parent_item(ecx.tcx.map.local_def_id(parent_id)); + encode_def_id_and_key(self, def_id); + let parent_id = tcx.map.get_parent(nitem.id); + self.encode_parent_item(tcx.map.local_def_id(parent_id)); self.encode_visibility(&nitem.vis); match nitem.node { hir::ForeignItemFn(ref fndecl, _) => { - encode_family(self.rbml_w, FN_FAMILY); - self.encode_bounds_and_type_for_item(nitem.id); - encode_name(self.rbml_w, nitem.name); - encode_attributes(self.rbml_w, &nitem.attrs); - let stab = ecx.tcx.lookup_stability(ecx.tcx.map.local_def_id(nitem.id)); - let depr = ecx.tcx.lookup_deprecation(ecx.tcx.map.local_def_id(nitem.id)); - encode_stability(self.rbml_w, stab); - encode_deprecation(self.rbml_w, depr); + encode_family(self, FN_FAMILY); + self.encode_bounds_and_type_for_item(def_id); + encode_name(self, nitem.name); + encode_attributes(self, &nitem.attrs); + let stab = tcx.lookup_stability(tcx.map.local_def_id(nitem.id)); + let depr = tcx.lookup_deprecation(tcx.map.local_def_id(nitem.id)); + encode_stability(self, stab); + encode_deprecation(self, depr); self.encode_method_argument_names(&fndecl); } hir::ForeignItemStatic(_, mutbl) => { if mutbl { - encode_family(self.rbml_w, 'b'); + encode_family(self, 'b'); } else { - encode_family(self.rbml_w, 'c'); + encode_family(self, 'c'); } - self.encode_bounds_and_type_for_item(nitem.id); - encode_attributes(self.rbml_w, &nitem.attrs); - let stab = ecx.tcx.lookup_stability(ecx.tcx.map.local_def_id(nitem.id)); - let depr = ecx.tcx.lookup_deprecation(ecx.tcx.map.local_def_id(nitem.id)); - encode_stability(self.rbml_w, stab); - encode_deprecation(self.rbml_w, depr); - encode_name(self.rbml_w, nitem.name); + self.encode_bounds_and_type_for_item(def_id); + encode_attributes(self, &nitem.attrs); + let stab = tcx.lookup_stability(tcx.map.local_def_id(nitem.id)); + let depr = tcx.lookup_deprecation(tcx.map.local_def_id(nitem.id)); + encode_stability(self, stab); + encode_deprecation(self, depr); + encode_name(self, nitem.name); } } } } -struct EncodeVisitor<'a, 'ecx: 'a, 'tcx: 'ecx, 'encoder: 'ecx> { - index: &'a mut IndexBuilder<'ecx, 'tcx, 'encoder>, +struct EncodeVisitor<'a, 'b: 'a, 'tcx: 'b> { + index: IndexBuilder<'a, 'b, 'tcx>, } -impl<'a, 'ecx, 'tcx, 'encoder> Visitor<'tcx> for EncodeVisitor<'a, 'ecx, 'tcx, 'encoder> { +impl<'a, 'b, 'tcx> Visitor<'tcx> for EncodeVisitor<'a, 'b, 'tcx> { fn visit_expr(&mut self, ex: &'tcx hir::Expr) { intravisit::walk_expr(self, ex); self.index.encode_info_for_expr(ex); } fn visit_item(&mut self, item: &'tcx hir::Item) { intravisit::walk_item(self, item); - let def_id = self.index.ecx().tcx.map.local_def_id(item.id); + let def_id = self.index.tcx.map.local_def_id(item.id); match item.node { hir::ItemExternCrate(_) | hir::ItemUse(_) => (), // ignore these _ => self.index.record(def_id, @@ -1326,7 +1291,7 @@ impl<'a, 'ecx, 'tcx, 'encoder> Visitor<'tcx> for EncodeVisitor<'a, 'ecx, 'tcx, ' } fn visit_foreign_item(&mut self, ni: &'tcx hir::ForeignItem) { intravisit::walk_foreign_item(self, ni); - let def_id = self.index.ecx().tcx.map.local_def_id(ni.id); + let def_id = self.index.tcx.map.local_def_id(ni.id); self.index.record(def_id, ItemContentBuilder::encode_info_for_foreign_item, (def_id, ni)); @@ -1337,135 +1302,130 @@ impl<'a, 'ecx, 'tcx, 'encoder> Visitor<'tcx> for EncodeVisitor<'a, 'ecx, 'tcx, ' } } -impl<'a, 'tcx, 'encoder> IndexBuilder<'a, 'tcx, 'encoder> { +impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { fn encode_info_for_ty(&mut self, ty: &hir::Ty) { - let ecx = self.ecx(); if let hir::TyImplTrait(_) = ty.node { - let def_id = ecx.tcx.map.local_def_id(ty.id); + let def_id = self.tcx.map.local_def_id(ty.id); self.record(def_id, ItemContentBuilder::encode_info_for_anon_ty, - (def_id, ty.id)); + def_id); } } fn encode_info_for_expr(&mut self, expr: &hir::Expr) { - let ecx = self.ecx(); - match expr.node { hir::ExprClosure(..) => { - let def_id = ecx.tcx.map.local_def_id(expr.id); + let def_id = self.tcx.map.local_def_id(expr.id); self.record(def_id, ItemContentBuilder::encode_info_for_closure, - (def_id, expr.id)); + def_id); } _ => { } } } } -impl<'a, 'tcx, 'encoder> ItemContentBuilder<'a, 'tcx, 'encoder> { - fn encode_info_for_anon_ty(&mut self, (def_id, ty_id): (DefId, NodeId)) { - let ecx = self.ecx; - encode_def_id_and_key(ecx, self.rbml_w, def_id); - encode_family(self.rbml_w, 'y'); - self.encode_bounds_and_type_for_item(ty_id); +impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { + fn encode_info_for_anon_ty(&mut self, def_id: DefId) { + encode_def_id_and_key(self, def_id); + encode_family(self, 'y'); + self.encode_bounds_and_type_for_item(def_id); } - fn encode_info_for_closure(&mut self, (def_id, expr_id): (DefId, NodeId)) { - let ecx = self.ecx; - encode_def_id_and_key(ecx, self.rbml_w, def_id); - encode_name(self.rbml_w, syntax::parse::token::intern("")); + fn encode_info_for_closure(&mut self, def_id: DefId) { + let tcx = self.tcx; + encode_def_id_and_key(self, def_id); + encode_name(self, syntax::parse::token::intern("")); - self.rbml_w.start_tag(tag_items_closure_ty); - write_closure_type(ecx, - self.rbml_w, - &ecx.tcx.tables.borrow().closure_tys[&def_id]); - self.rbml_w.end_tag(); + self.start_tag(tag_items_closure_ty); + write_closure_type(self, + &tcx.tables.borrow().closure_tys[&def_id]); + self.end_tag(); - self.rbml_w.start_tag(tag_items_closure_kind); - ecx.tcx.closure_kind(def_id).encode(self.rbml_w).unwrap(); - self.rbml_w.end_tag(); + self.start_tag(tag_items_closure_kind); + tcx.closure_kind(def_id).encode(self.ecx).unwrap(); + self.end_tag(); - assert!(ecx.mir_map.map.contains_key(&def_id)); - self.encode_mir(expr_id); + assert!(self.mir_map.map.contains_key(&def_id)); + self.encode_mir(def_id); } } -fn encode_info_for_items<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, - rbml_w: &mut Encoder) +fn encode_info_for_items<'a, 'tcx>(ecx: &mut EncodeContext<'a, 'tcx>) -> (IndexData, FnvHashMap, u32>) { let krate = ecx.tcx.map.krate(); - rbml_w.start_tag(tag_items_data); + ecx.start_tag(tag_items_data); let fields = { - let mut index = IndexBuilder::new(ecx, rbml_w); + let mut index = IndexBuilder::new(ecx); index.record(DefId::local(CRATE_DEF_INDEX), ItemContentBuilder::encode_info_for_mod, FromId(CRATE_NODE_ID, (&krate.module, &[], syntax::parse::token::intern(&ecx.link_meta.crate_name), &hir::Public))); - krate.visit_all_items(&mut EncodeVisitor { - index: &mut index, - }); - index.into_fields() + let mut visitor = EncodeVisitor { + index: index, + }; + krate.visit_all_items(&mut visitor); + visitor.index.into_fields() }; - rbml_w.end_tag(); + ecx.end_tag(); fields } -fn encode_item_index(rbml_w: &mut Encoder, index: IndexData) { - rbml_w.start_tag(tag_index); - index.write_index(rbml_w.writer); - rbml_w.end_tag(); +fn encode_item_index(ecx: &mut EncodeContext, index: IndexData) { + ecx.start_tag(tag_index); + index.write_index(&mut ecx.writer); + ecx.end_tag(); } -fn encode_attributes(rbml_w: &mut Encoder, attrs: &[ast::Attribute]) { - rbml_w.start_tag(tag_attributes); - rbml_w.emit_opaque(|opaque_encoder| { +fn encode_attributes(ecx: &mut EncodeContext, attrs: &[ast::Attribute]) { + ecx.start_tag(tag_attributes); + ecx.emit_opaque(|opaque_encoder| { attrs.encode(opaque_encoder) }).unwrap(); - rbml_w.end_tag(); + ecx.end_tag(); } -fn encode_unsafety(rbml_w: &mut Encoder, unsafety: hir::Unsafety) { +fn encode_unsafety(ecx: &mut EncodeContext, unsafety: hir::Unsafety) { let byte: u8 = match unsafety { hir::Unsafety::Normal => 0, hir::Unsafety::Unsafe => 1, }; - rbml_w.wr_tagged_u8(tag_unsafety, byte); + ecx.wr_tagged_u8(tag_unsafety, byte); } -fn encode_paren_sugar(rbml_w: &mut Encoder, paren_sugar: bool) { +fn encode_paren_sugar(ecx: &mut EncodeContext, paren_sugar: bool) { let byte: u8 = if paren_sugar {1} else {0}; - rbml_w.wr_tagged_u8(tag_paren_sugar, byte); + ecx.wr_tagged_u8(tag_paren_sugar, byte); } -fn encode_defaulted(rbml_w: &mut Encoder, is_defaulted: bool) { +fn encode_defaulted(ecx: &mut EncodeContext, is_defaulted: bool) { let byte: u8 = if is_defaulted {1} else {0}; - rbml_w.wr_tagged_u8(tag_defaulted_trait, byte); + ecx.wr_tagged_u8(tag_defaulted_trait, byte); } -fn encode_associated_type_names(rbml_w: &mut Encoder, names: &[Name]) { - rbml_w.start_tag(tag_associated_type_names); +fn encode_associated_type_names(ecx: &mut EncodeContext, names: &[Name]) { + ecx.start_tag(tag_associated_type_names); for &name in names { - rbml_w.wr_tagged_str(tag_associated_type_name, &name.as_str()); + ecx.wr_tagged_str(tag_associated_type_name, &name.as_str()); } - rbml_w.end_tag(); + ecx.end_tag(); } -fn encode_polarity(rbml_w: &mut Encoder, polarity: hir::ImplPolarity) { +fn encode_polarity(ecx: &mut EncodeContext, polarity: hir::ImplPolarity) { let byte: u8 = match polarity { hir::ImplPolarity::Positive => 0, hir::ImplPolarity::Negative => 1, }; - rbml_w.wr_tagged_u8(tag_polarity, byte); + ecx.wr_tagged_u8(tag_polarity, byte); } -fn encode_crate_deps(rbml_w: &mut Encoder, cstore: &cstore::CStore) { +fn encode_crate_deps(ecx: &mut EncodeContext, cstore: &cstore::CStore) { fn get_ordered_deps(cstore: &cstore::CStore) -> Vec<(CrateNum, Rc)> { // Pull the cnums and name,vers,hash out of cstore @@ -1491,64 +1451,64 @@ fn encode_crate_deps(rbml_w: &mut Encoder, cstore: &cstore::CStore) { // the assumption that they are numbered 1 to n. // FIXME (#2166): This is not nearly enough to support correct versioning // but is enough to get transitive crate dependencies working. - rbml_w.start_tag(tag_crate_deps); + ecx.start_tag(tag_crate_deps); for (_cnum, dep) in get_ordered_deps(cstore) { - encode_crate_dep(rbml_w, &dep); + encode_crate_dep(ecx, &dep); } - rbml_w.end_tag(); + ecx.end_tag(); } -fn encode_lang_items(ecx: &EncodeContext, rbml_w: &mut Encoder) { - rbml_w.start_tag(tag_lang_items); +fn encode_lang_items(ecx: &mut EncodeContext) { + ecx.start_tag(tag_lang_items); for (i, &opt_def_id) in ecx.tcx.lang_items.items().iter().enumerate() { if let Some(def_id) = opt_def_id { if def_id.is_local() { - rbml_w.start_tag(tag_lang_items_item); - rbml_w.wr_tagged_u32(tag_lang_items_item_id, i as u32); - rbml_w.wr_tagged_u32(tag_lang_items_item_index, def_id.index.as_u32()); - rbml_w.end_tag(); + ecx.start_tag(tag_lang_items_item); + ecx.wr_tagged_u32(tag_lang_items_item_id, i as u32); + ecx.wr_tagged_u32(tag_lang_items_item_index, def_id.index.as_u32()); + ecx.end_tag(); } } } for i in &ecx.tcx.lang_items.missing { - rbml_w.wr_tagged_u32(tag_lang_items_missing, *i as u32); + ecx.wr_tagged_u32(tag_lang_items_missing, *i as u32); } - rbml_w.end_tag(); // tag_lang_items + ecx.end_tag(); // tag_lang_items } -fn encode_native_libraries(ecx: &EncodeContext, rbml_w: &mut Encoder) { - rbml_w.start_tag(tag_native_libraries); +fn encode_native_libraries(ecx: &mut EncodeContext) { + ecx.start_tag(tag_native_libraries); for &(ref lib, kind) in ecx.tcx.sess.cstore.used_libraries().iter() { match kind { cstore::NativeStatic => {} // these libraries are not propagated cstore::NativeFramework | cstore::NativeUnknown => { - rbml_w.start_tag(tag_native_libraries_lib); - rbml_w.wr_tagged_u32(tag_native_libraries_kind, kind as u32); - rbml_w.wr_tagged_str(tag_native_libraries_name, lib); - rbml_w.end_tag(); + ecx.start_tag(tag_native_libraries_lib); + ecx.wr_tagged_u32(tag_native_libraries_kind, kind as u32); + ecx.wr_tagged_str(tag_native_libraries_name, lib); + ecx.end_tag(); } } } - rbml_w.end_tag(); + ecx.end_tag(); } -fn encode_plugin_registrar_fn(ecx: &EncodeContext, rbml_w: &mut Encoder) { +fn encode_plugin_registrar_fn(ecx: &mut EncodeContext) { match ecx.tcx.sess.plugin_registrar_fn.get() { Some(id) => { let def_id = ecx.tcx.map.local_def_id(id); - rbml_w.wr_tagged_u32(tag_plugin_registrar_fn, def_id.index.as_u32()); + ecx.wr_tagged_u32(tag_plugin_registrar_fn, def_id.index.as_u32()); } None => {} } } -fn encode_codemap(ecx: &EncodeContext, rbml_w: &mut Encoder) { - rbml_w.start_tag(tag_codemap); +fn encode_codemap(ecx: &mut EncodeContext) { + ecx.start_tag(tag_codemap); let codemap = ecx.tcx.sess.codemap(); for filemap in &codemap.files.borrow()[..] { @@ -1561,66 +1521,62 @@ fn encode_codemap(ecx: &EncodeContext, rbml_w: &mut Encoder) { continue; } - rbml_w.start_tag(tag_codemap_filemap); - rbml_w.emit_opaque(|opaque_encoder| { + ecx.start_tag(tag_codemap_filemap); + ecx.emit_opaque(|opaque_encoder| { filemap.encode(opaque_encoder) }).unwrap(); - rbml_w.end_tag(); + ecx.end_tag(); } - rbml_w.end_tag(); + ecx.end_tag(); } /// Serialize the text of the exported macros -fn encode_macro_defs(rbml_w: &mut Encoder, - krate: &hir::Crate, - tcx: TyCtxt) { - rbml_w.start_tag(tag_macro_defs); +fn encode_macro_defs(ecx: &mut EncodeContext, + krate: &hir::Crate) { + ecx.start_tag(tag_macro_defs); for def in &krate.exported_macros { - rbml_w.start_tag(tag_macro_def); + ecx.start_tag(tag_macro_def); - encode_name(rbml_w, def.name); - encode_attributes(rbml_w, &def.attrs); + encode_name(ecx, def.name); + encode_attributes(ecx, &def.attrs); let &BytePos(lo) = &def.span.lo; let &BytePos(hi) = &def.span.hi; - rbml_w.wr_tagged_u32(tag_macro_def_span_lo, lo); - rbml_w.wr_tagged_u32(tag_macro_def_span_hi, hi); + ecx.wr_tagged_u32(tag_macro_def_span_lo, lo); + ecx.wr_tagged_u32(tag_macro_def_span_hi, hi); - rbml_w.wr_tagged_str(tag_macro_def_body, - &::syntax::print::pprust::tts_to_string(&def.body)); + ecx.wr_tagged_str(tag_macro_def_body, + &::syntax::print::pprust::tts_to_string(&def.body)); - rbml_w.end_tag(); + ecx.end_tag(); } - rbml_w.end_tag(); + ecx.end_tag(); - if tcx.sess.crate_types.borrow().contains(&CrateTypeRustcMacro) { - let id = tcx.sess.derive_registrar_fn.get().unwrap(); - let did = tcx.map.local_def_id(id); - rbml_w.wr_tagged_u32(tag_macro_derive_registrar, did.index.as_u32()); + if ecx.tcx.sess.crate_types.borrow().contains(&CrateTypeRustcMacro) { + let id = ecx.tcx.sess.derive_registrar_fn.get().unwrap(); + let did = ecx.tcx.map.local_def_id(id); + ecx.wr_tagged_u32(tag_macro_derive_registrar, did.index.as_u32()); } } -fn encode_struct_field_attrs(ecx: &EncodeContext, - rbml_w: &mut Encoder, - krate: &hir::Crate) { - struct StructFieldVisitor<'a, 'b:'a, 'c:'a, 'tcx:'b> { - ecx: &'a EncodeContext<'b, 'tcx>, - rbml_w: &'a mut Encoder<'c>, +fn encode_struct_field_attrs(ecx: &mut EncodeContext, krate: &hir::Crate) { + struct StructFieldVisitor<'a, 'b:'a, 'tcx:'b> { + ecx: &'a mut EncodeContext<'b, 'tcx> } - impl<'a, 'b, 'c, 'tcx, 'v> Visitor<'v> for StructFieldVisitor<'a, 'b, 'c, 'tcx> { + impl<'a, 'b, 'tcx, 'v> Visitor<'v> for StructFieldVisitor<'a, 'b, 'tcx> { fn visit_struct_field(&mut self, field: &hir::StructField) { - self.rbml_w.start_tag(tag_struct_field); + self.ecx.start_tag(tag_struct_field); let def_id = self.ecx.tcx.map.local_def_id(field.id); - encode_def_id(self.rbml_w, def_id); - encode_attributes(self.rbml_w, &field.attrs); - self.rbml_w.end_tag(); + encode_def_id(self.ecx, def_id); + encode_attributes(self.ecx, &field.attrs); + self.ecx.end_tag(); } } - rbml_w.start_tag(tag_struct_fields); - krate.visit_all_items(&mut StructFieldVisitor { ecx: ecx, rbml_w: rbml_w }); - rbml_w.end_tag(); + ecx.start_tag(tag_struct_fields); + krate.visit_all_items(&mut StructFieldVisitor { ecx: ecx }); + ecx.end_tag(); } @@ -1644,25 +1600,23 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ImplVisitor<'a, 'tcx> { } /// Encodes an index, mapping each trait to its (local) implementations. -fn encode_impls<'a>(ecx: &'a EncodeContext, - krate: &hir::Crate, - rbml_w: &'a mut Encoder) { +fn encode_impls(ecx: &mut EncodeContext, krate: &hir::Crate) { let mut visitor = ImplVisitor { tcx: ecx.tcx, impls: FnvHashMap() }; krate.visit_all_items(&mut visitor); - rbml_w.start_tag(tag_impls); + ecx.start_tag(tag_impls); for (trait_, trait_impls) in visitor.impls { - rbml_w.start_tag(tag_impls_trait); - encode_def_id(rbml_w, trait_); + ecx.start_tag(tag_impls_trait); + encode_def_id(ecx, trait_); for impl_ in trait_impls { - rbml_w.wr_tagged_u64(tag_impls_trait_impl, def_to_u64(impl_)); + ecx.wr_tagged_u64(tag_impls_trait_impl, def_to_u64(impl_)); } - rbml_w.end_tag(); + ecx.end_tag(); } - rbml_w.end_tag(); + ecx.end_tag(); } // Encodes all reachable symbols in this crate into the metadata. @@ -1671,47 +1625,47 @@ fn encode_impls<'a>(ecx: &'a EncodeContext, // middle::reachable module but filters out items that either don't have a // symbol associated with them (they weren't translated) or if they're an FFI // definition (as that's not defined in this crate). -fn encode_reachable(ecx: &EncodeContext, rbml_w: &mut Encoder) { - rbml_w.start_tag(tag_reachable_ids); +fn encode_reachable(ecx: &mut EncodeContext) { + ecx.start_tag(tag_reachable_ids); for &id in ecx.reachable { let def_id = ecx.tcx.map.local_def_id(id); - rbml_w.wr_tagged_u32(tag_reachable_id, def_id.index.as_u32()); + ecx.wr_tagged_u32(tag_reachable_id, def_id.index.as_u32()); } - rbml_w.end_tag(); + ecx.end_tag(); } -fn encode_crate_dep(rbml_w: &mut Encoder, +fn encode_crate_dep(ecx: &mut EncodeContext, dep: &cstore::CrateMetadata) { - rbml_w.start_tag(tag_crate_dep); - rbml_w.wr_tagged_str(tag_crate_dep_crate_name, &dep.name()); + ecx.start_tag(tag_crate_dep); + ecx.wr_tagged_str(tag_crate_dep_crate_name, &dep.name()); let hash = decoder::get_crate_hash(dep.data()); - rbml_w.wr_tagged_u64(tag_crate_dep_hash, hash.as_u64()); - rbml_w.wr_tagged_u8(tag_crate_dep_explicitly_linked, - dep.explicitly_linked.get() as u8); - rbml_w.end_tag(); + ecx.wr_tagged_u64(tag_crate_dep_hash, hash.as_u64()); + ecx.wr_tagged_u8(tag_crate_dep_explicitly_linked, + dep.explicitly_linked.get() as u8); + ecx.end_tag(); } -fn encode_hash(rbml_w: &mut Encoder, hash: &Svh) { - rbml_w.wr_tagged_u64(tag_crate_hash, hash.as_u64()); +fn encode_hash(ecx: &mut EncodeContext, hash: &Svh) { + ecx.wr_tagged_u64(tag_crate_hash, hash.as_u64()); } -fn encode_rustc_version(rbml_w: &mut Encoder) { - rbml_w.wr_tagged_str(tag_rustc_version, &rustc_version()); +fn encode_rustc_version(ecx: &mut EncodeContext) { + ecx.wr_tagged_str(tag_rustc_version, &rustc_version()); } -fn encode_crate_name(rbml_w: &mut Encoder, crate_name: &str) { - rbml_w.wr_tagged_str(tag_crate_crate_name, crate_name); +fn encode_crate_name(ecx: &mut EncodeContext, crate_name: &str) { + ecx.wr_tagged_str(tag_crate_crate_name, crate_name); } -fn encode_crate_disambiguator(rbml_w: &mut Encoder, crate_disambiguator: &str) { - rbml_w.wr_tagged_str(tag_crate_disambiguator, crate_disambiguator); +fn encode_crate_disambiguator(ecx: &mut EncodeContext, crate_disambiguator: &str) { + ecx.wr_tagged_str(tag_crate_disambiguator, crate_disambiguator); } -fn encode_crate_triple(rbml_w: &mut Encoder, triple: &str) { - rbml_w.wr_tagged_str(tag_crate_triple, triple); +fn encode_crate_triple(ecx: &mut EncodeContext, triple: &str) { + ecx.wr_tagged_str(tag_crate_triple, triple); } -fn encode_dylib_dependency_formats(rbml_w: &mut Encoder, ecx: &EncodeContext) { +fn encode_dylib_dependency_formats(ecx: &mut EncodeContext) { let tag = tag_dylib_dependency_formats; match ecx.tcx.sess.dependency_formats.borrow().get(&config::CrateTypeDylib) { Some(arr) => { @@ -1724,37 +1678,32 @@ fn encode_dylib_dependency_formats(rbml_w: &mut Encoder, ecx: &EncodeContext) { }; Some(format!("{}:{}", i + 1, kind)) }).collect::>(); - rbml_w.wr_tagged_str(tag, &s.join(",")); + ecx.wr_tagged_str(tag, &s.join(",")); } None => { - rbml_w.wr_tagged_str(tag, ""); + ecx.wr_tagged_str(tag, ""); } } } -fn encode_panic_strategy(rbml_w: &mut Encoder, ecx: &EncodeContext) { +fn encode_panic_strategy(ecx: &mut EncodeContext) { match ecx.tcx.sess.opts.cg.panic { PanicStrategy::Unwind => { - rbml_w.wr_tagged_u8(tag_panic_strategy, b'U'); + ecx.wr_tagged_u8(tag_panic_strategy, b'U'); } PanicStrategy::Abort => { - rbml_w.wr_tagged_u8(tag_panic_strategy, b'A'); + ecx.wr_tagged_u8(tag_panic_strategy, b'A'); } } } -pub fn encode_metadata(ecx: EncodeContext, krate: &hir::Crate) -> Vec { - let mut wr = Cursor::new(Vec::new()); - - { - let mut rbml_w = Encoder::new(&mut wr); - encode_metadata_inner(&mut rbml_w, &ecx, krate) - } +pub fn encode_metadata(mut ecx: EncodeContext, krate: &hir::Crate) -> Vec { + encode_metadata_inner(&mut ecx, krate); // RBML compacts the encoded bytes whenever appropriate, // so there are some garbages left after the end of the data. - let metalen = wr.seek(SeekFrom::Current(0)).unwrap() as usize; - let mut v = wr.into_inner(); + let metalen = ecx.rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() as usize; + let mut v = ecx.rbml_w.writer.into_inner(); v.truncate(metalen); assert_eq!(v.len(), metalen); @@ -1797,9 +1746,7 @@ pub fn encode_metadata(ecx: EncodeContext, krate: &hir::Crate) -> Vec { result } -fn encode_metadata_inner(rbml_w: &mut Encoder, - ecx: &EncodeContext, - krate: &hir::Crate) { +fn encode_metadata_inner(ecx: &mut EncodeContext, krate: &hir::Crate) { struct Stats { attr_bytes: u64, dep_bytes: u64, @@ -1833,78 +1780,81 @@ fn encode_metadata_inner(rbml_w: &mut Encoder, total_bytes: 0, }; - encode_rustc_version(rbml_w); - encode_crate_name(rbml_w, &ecx.link_meta.crate_name); - encode_crate_triple(rbml_w, &ecx.tcx.sess.opts.target_triple); - encode_hash(rbml_w, &ecx.link_meta.crate_hash); - encode_crate_disambiguator(rbml_w, &ecx.tcx.sess.local_crate_disambiguator()); - encode_dylib_dependency_formats(rbml_w, &ecx); - encode_panic_strategy(rbml_w, &ecx); + encode_rustc_version(ecx); + + let tcx = ecx.tcx; + let link_meta = ecx.link_meta; + encode_crate_name(ecx, &link_meta.crate_name); + encode_crate_triple(ecx, &tcx.sess.opts.target_triple); + encode_hash(ecx, &link_meta.crate_hash); + encode_crate_disambiguator(ecx, &tcx.sess.local_crate_disambiguator()); + encode_dylib_dependency_formats(ecx); + encode_panic_strategy(ecx); - let mut i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap(); - encode_attributes(rbml_w, &krate.attrs); - stats.attr_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i; + let mut i = ecx.writer.seek(SeekFrom::Current(0)).unwrap(); + encode_attributes(ecx, &krate.attrs); + stats.attr_bytes = ecx.writer.seek(SeekFrom::Current(0)).unwrap() - i; - i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap(); - encode_crate_deps(rbml_w, ecx.cstore); - stats.dep_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i; + i = ecx.writer.seek(SeekFrom::Current(0)).unwrap(); + encode_crate_deps(ecx, ecx.cstore); + stats.dep_bytes = ecx.writer.seek(SeekFrom::Current(0)).unwrap() - i; // Encode the language items. - i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap(); - encode_lang_items(&ecx, rbml_w); - stats.lang_item_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i; + i = ecx.writer.seek(SeekFrom::Current(0)).unwrap(); + encode_lang_items(ecx); + stats.lang_item_bytes = ecx.writer.seek(SeekFrom::Current(0)).unwrap() - i; // Encode the native libraries used - i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap(); - encode_native_libraries(&ecx, rbml_w); - stats.native_lib_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i; + i = ecx.writer.seek(SeekFrom::Current(0)).unwrap(); + encode_native_libraries(ecx); + stats.native_lib_bytes = ecx.writer.seek(SeekFrom::Current(0)).unwrap() - i; // Encode the plugin registrar function - i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap(); - encode_plugin_registrar_fn(&ecx, rbml_w); - stats.plugin_registrar_fn_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i; + i = ecx.writer.seek(SeekFrom::Current(0)).unwrap(); + encode_plugin_registrar_fn(ecx); + stats.plugin_registrar_fn_bytes = ecx.writer.seek(SeekFrom::Current(0)).unwrap() - i; // Encode codemap - i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap(); - encode_codemap(&ecx, rbml_w); - stats.codemap_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i; + i = ecx.writer.seek(SeekFrom::Current(0)).unwrap(); + encode_codemap(ecx); + stats.codemap_bytes = ecx.writer.seek(SeekFrom::Current(0)).unwrap() - i; // Encode macro definitions - i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap(); - encode_macro_defs(rbml_w, krate, ecx.tcx); - stats.macro_defs_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i; + i = ecx.writer.seek(SeekFrom::Current(0)).unwrap(); + encode_macro_defs(ecx, krate); + stats.macro_defs_bytes = ecx.writer.seek(SeekFrom::Current(0)).unwrap() - i; // Encode the def IDs of impls, for coherence checking. - i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap(); - encode_impls(&ecx, krate, rbml_w); - stats.impl_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i; + i = ecx.writer.seek(SeekFrom::Current(0)).unwrap(); + encode_impls(ecx, krate); + stats.impl_bytes = ecx.writer.seek(SeekFrom::Current(0)).unwrap() - i; // Encode reachability info. - i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap(); - encode_reachable(&ecx, rbml_w); - stats.reachable_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i; + i = ecx.writer.seek(SeekFrom::Current(0)).unwrap(); + encode_reachable(ecx); + stats.reachable_bytes = ecx.writer.seek(SeekFrom::Current(0)).unwrap() - i; // Encode and index the items. - rbml_w.start_tag(tag_items); - i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap(); - let (items, xrefs) = encode_info_for_items(&ecx, rbml_w); - stats.item_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i; - rbml_w.end_tag(); + ecx.start_tag(tag_items); + i = ecx.writer.seek(SeekFrom::Current(0)).unwrap(); + let (items, xrefs) = encode_info_for_items(ecx); + stats.item_bytes = ecx.writer.seek(SeekFrom::Current(0)).unwrap() - i; + ecx.end_tag(); - i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap(); - encode_item_index(rbml_w, items); - stats.index_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i; + i = ecx.writer.seek(SeekFrom::Current(0)).unwrap(); + encode_item_index(ecx, items); + stats.index_bytes = ecx.writer.seek(SeekFrom::Current(0)).unwrap() - i; - i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap(); - encode_xrefs(&ecx, rbml_w, xrefs); - stats.xref_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i; + i = ecx.writer.seek(SeekFrom::Current(0)).unwrap(); + encode_xrefs(ecx, xrefs); + stats.xref_bytes = ecx.writer.seek(SeekFrom::Current(0)).unwrap() - i; - encode_struct_field_attrs(&ecx, rbml_w, krate); + encode_struct_field_attrs(ecx, krate); - stats.total_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap(); + stats.total_bytes = ecx.writer.seek(SeekFrom::Current(0)).unwrap(); if ecx.tcx.sess.meta_stats() { - for e in rbml_w.writer.get_ref() { + for e in ecx.writer.get_ref() { if *e == 0 { stats.zero_bytes += 1; } @@ -1935,7 +1885,6 @@ pub fn encoded_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, -> Vec { let mut wr = Cursor::new(Vec::new()); tyencode::enc_ty(&mut wr, &tyencode::ctxt { - diag: tcx.sess.diagnostic(), ds: def_id_to_string, tcx: tcx, abbrevs: &RefCell::new(FnvHashMap()) diff --git a/src/librustc_metadata/index_builder.rs b/src/librustc_metadata/index_builder.rs index 1d3d09d6bc2d7..de2f1c4fb0c85 100644 --- a/src/librustc_metadata/index_builder.rs +++ b/src/librustc_metadata/index_builder.rs @@ -65,7 +65,6 @@ use common::tag_items_data_item; use encoder::EncodeContext; use index::IndexData; -use rbml::writer::Encoder; use rustc::dep_graph::DepNode; use rustc::hir; use rustc::hir::def_id::DefId; @@ -73,43 +72,63 @@ use rustc::ty::{self, TyCtxt}; use rustc_data_structures::fnv::FnvHashMap; use syntax::ast; +use std::ops::{Deref, DerefMut}; + /// Builder that can encode new items, adding them into the index. /// Item encoding cannot be nested. -pub struct IndexBuilder<'a, 'tcx: 'a, 'encoder: 'a> { +pub struct IndexBuilder<'a, 'b: 'a, 'tcx: 'b> { items: IndexData, - builder: ItemContentBuilder<'a, 'tcx, 'encoder>, + builder: ItemContentBuilder<'a, 'b, 'tcx>, } /// Builder that can encode the content of items, but can't start a /// new item itself. Most code is attached to here. -pub struct ItemContentBuilder<'a, 'tcx: 'a, 'encoder: 'a> { +pub struct ItemContentBuilder<'a, 'b: 'a, 'tcx: 'b> { xrefs: FnvHashMap, u32>, // sequentially-assigned - pub ecx: &'a EncodeContext<'a, 'tcx>, - pub rbml_w: &'a mut Encoder<'encoder>, + pub ecx: &'a mut EncodeContext<'b, 'tcx>, +} + +impl<'a, 'b, 'tcx> Deref for IndexBuilder<'a, 'b, 'tcx> { + type Target = EncodeContext<'b, 'tcx>; + fn deref(&self) -> &Self::Target { + self.builder.ecx + } +} + +impl<'a, 'b, 'tcx> DerefMut for IndexBuilder<'a, 'b, 'tcx> { + fn deref_mut(&mut self) -> &mut Self::Target { + self.builder.ecx + } +} + +impl<'a, 'b, 'tcx> Deref for ItemContentBuilder<'a, 'b, 'tcx> { + type Target = EncodeContext<'b, 'tcx>; + fn deref(&self) -> &Self::Target { + self.ecx + } +} + +impl<'a, 'b, 'tcx> DerefMut for ItemContentBuilder<'a, 'b, 'tcx> { + fn deref_mut(&mut self) -> &mut Self::Target { + self.ecx + } } /// "interned" entries referenced by id #[derive(PartialEq, Eq, Hash)] pub enum XRef<'tcx> { Predicate(ty::Predicate<'tcx>) } -impl<'a, 'tcx, 'encoder> IndexBuilder<'a, 'tcx, 'encoder> { - pub fn new(ecx: &'a EncodeContext<'a, 'tcx>, - rbml_w: &'a mut Encoder<'encoder>) - -> Self { +impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { + pub fn new(ecx: &'a mut EncodeContext<'b, 'tcx>) -> Self { IndexBuilder { items: IndexData::new(ecx.tcx.map.num_local_def_ids()), builder: ItemContentBuilder { ecx: ecx, xrefs: FnvHashMap(), - rbml_w: rbml_w, }, } } - pub fn ecx(&self) -> &'a EncodeContext<'a, 'tcx> { - self.builder.ecx() - } - /// Emit the data for a def-id to the metadata. The function to /// emit the data is `op`, and it will be given `data` as /// arguments. This `record` function will start/end an RBML tag @@ -129,17 +148,17 @@ impl<'a, 'tcx, 'encoder> IndexBuilder<'a, 'tcx, 'encoder> { /// content system. pub fn record(&mut self, id: DefId, - op: fn(&mut ItemContentBuilder<'a, 'tcx, 'encoder>, DATA), + op: fn(&mut ItemContentBuilder<'a, 'b, 'tcx>, DATA), data: DATA) where DATA: DepGraphRead { - let position = self.builder.rbml_w.mark_stable_position(); + let position = self.builder.ecx.mark_stable_position(); self.items.record(id, position); - let _task = self.ecx().tcx.dep_graph.in_task(DepNode::MetaData(id)); - self.builder.rbml_w.start_tag(tag_items_data_item).unwrap(); - data.read(self.ecx().tcx); + let _task = self.tcx.dep_graph.in_task(DepNode::MetaData(id)); + self.builder.ecx.start_tag(tag_items_data_item).unwrap(); + data.read(self.tcx); op(&mut self.builder, data); - self.builder.rbml_w.end_tag().unwrap(); + self.builder.ecx.end_tag().unwrap(); } pub fn into_fields(self) -> (IndexData, FnvHashMap, u32>) { @@ -147,11 +166,7 @@ impl<'a, 'tcx, 'encoder> IndexBuilder<'a, 'tcx, 'encoder> { } } -impl<'a, 'tcx, 'encoder> ItemContentBuilder<'a, 'tcx, 'encoder> { - pub fn ecx(&self) -> &'a EncodeContext<'a, 'tcx> { - self.ecx - } - +impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { pub fn add_xref(&mut self, xref: XRef<'tcx>) -> u32 { let old_len = self.xrefs.len() as u32; *self.xrefs.entry(xref).or_insert(old_len) diff --git a/src/librustc_metadata/rbml/writer.rs b/src/librustc_metadata/rbml/writer.rs index 17b3c392edb36..b49686e2379d6 100644 --- a/src/librustc_metadata/rbml/writer.rs +++ b/src/librustc_metadata/rbml/writer.rs @@ -21,8 +21,8 @@ use rustc_serialize as serialize; pub type EncodeResult = io::Result<()>; // rbml writing -pub struct Encoder<'a> { - pub writer: &'a mut Cursor>, +pub struct Encoder { + pub writer: Cursor>, size_positions: Vec, relax_limit: u64, // do not move encoded bytes before this position } @@ -65,10 +65,10 @@ pub fn write_vuint(w: &mut W, n: usize) -> EncodeResult { Err(io::Error::new(io::ErrorKind::Other, &format!("isize too big: {}", n)[..])) } -impl<'a> Encoder<'a> { - pub fn new(w: &'a mut Cursor>) -> Encoder<'a> { +impl Encoder { + pub fn new() -> Encoder { Encoder { - writer: w, + writer: Cursor::new(vec![]), size_positions: vec![], relax_limit: 0, } @@ -79,7 +79,7 @@ impl<'a> Encoder<'a> { assert!(tag_id >= NUM_IMPLICIT_TAGS); // Write the enum ID: - write_tag(self.writer, tag_id)?; + write_tag(&mut self.writer, tag_id)?; // Write a placeholder four-byte size. let cur_pos = self.writer.seek(SeekFrom::Current(0))?; @@ -107,11 +107,11 @@ impl<'a> Encoder<'a> { } // overwrite the size and data and continue - write_vuint(self.writer, size)?; + write_vuint(&mut self.writer, size)?; self.writer.write_all(&buf[..size])?; } else { // overwrite the size with an overlong encoding and skip past the data - write_sized_vuint(self.writer, size, 4)?; + write_sized_vuint(&mut self.writer, size, 4)?; self.writer.seek(SeekFrom::Start(cur_pos))?; } @@ -129,8 +129,8 @@ impl<'a> Encoder<'a> { pub fn wr_tagged_bytes(&mut self, tag_id: usize, b: &[u8]) -> EncodeResult { assert!(tag_id >= NUM_IMPLICIT_TAGS); - write_tag(self.writer, tag_id)?; - write_vuint(self.writer, b.len())?; + write_tag(&mut self.writer, tag_id)?; + write_vuint(&mut self.writer, b.len())?; self.writer.write_all(b) } @@ -183,7 +183,7 @@ impl<'a> Encoder<'a> { // for auto-serialization fn wr_tagged_raw_bytes(&mut self, tag_id: usize, b: &[u8]) -> EncodeResult { - write_tag(self.writer, tag_id)?; + write_tag(&mut self.writer, tag_id)?; self.writer.write_all(b) } @@ -243,7 +243,7 @@ impl<'a> Encoder<'a> { } } -impl<'a> Encoder<'a> { +impl Encoder { // used internally to emit things like the vector length and so on fn _emit_tagged_sub(&mut self, v: usize) -> EncodeResult { if v as u8 as usize == v { @@ -262,7 +262,7 @@ impl<'a> Encoder<'a> { self.start_tag(EsOpaque as usize)?; { - let mut opaque_encoder = opaque::Encoder::new(self.writer); + let mut opaque_encoder = opaque::Encoder::new(&mut self.writer); f(&mut opaque_encoder)?; } @@ -271,7 +271,7 @@ impl<'a> Encoder<'a> { } } -impl<'a> serialize::Encoder for Encoder<'a> { +impl<'a, 'tcx> serialize::Encoder for ::encoder::EncodeContext<'a, 'tcx> { type Error = io::Error; fn emit_nil(&mut self) -> EncodeResult { @@ -355,7 +355,7 @@ impl<'a> serialize::Encoder for Encoder<'a> { } fn emit_enum(&mut self, _name: &str, f: F) -> EncodeResult - where F: FnOnce(&mut Encoder<'a>) -> EncodeResult + where F: FnOnce(&mut Self) -> EncodeResult { self.start_tag(EsEnum as usize)?; f(self)?; @@ -363,14 +363,14 @@ impl<'a> serialize::Encoder for Encoder<'a> { } fn emit_enum_variant(&mut self, _: &str, v_id: usize, _: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Encoder<'a>) -> EncodeResult + where F: FnOnce(&mut Self) -> EncodeResult { self._emit_tagged_sub(v_id)?; f(self) } fn emit_enum_variant_arg(&mut self, _: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Encoder<'a>) -> EncodeResult + where F: FnOnce(&mut Self) -> EncodeResult { f(self) } @@ -381,53 +381,53 @@ impl<'a> serialize::Encoder for Encoder<'a> { cnt: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Encoder<'a>) -> EncodeResult + where F: FnOnce(&mut Self) -> EncodeResult { self.emit_enum_variant(v_name, v_id, cnt, f) } fn emit_enum_struct_variant_field(&mut self, _: &str, idx: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Encoder<'a>) -> EncodeResult + where F: FnOnce(&mut Self) -> EncodeResult { self.emit_enum_variant_arg(idx, f) } fn emit_struct(&mut self, _: &str, _len: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Encoder<'a>) -> EncodeResult + where F: FnOnce(&mut Self) -> EncodeResult { f(self) } fn emit_struct_field(&mut self, _name: &str, _: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Encoder<'a>) -> EncodeResult + where F: FnOnce(&mut Self) -> EncodeResult { f(self) } fn emit_tuple(&mut self, len: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Encoder<'a>) -> EncodeResult + where F: FnOnce(&mut Self) -> EncodeResult { self.emit_seq(len, f) } fn emit_tuple_arg(&mut self, idx: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Encoder<'a>) -> EncodeResult + where F: FnOnce(&mut Self) -> EncodeResult { self.emit_seq_elt(idx, f) } fn emit_tuple_struct(&mut self, _: &str, len: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Encoder<'a>) -> EncodeResult + where F: FnOnce(&mut Self) -> EncodeResult { self.emit_seq(len, f) } fn emit_tuple_struct_arg(&mut self, idx: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Encoder<'a>) -> EncodeResult + where F: FnOnce(&mut Self) -> EncodeResult { self.emit_seq_elt(idx, f) } fn emit_option(&mut self, f: F) -> EncodeResult - where F: FnOnce(&mut Encoder<'a>) -> EncodeResult + where F: FnOnce(&mut Self) -> EncodeResult { self.emit_enum("Option", f) } @@ -435,14 +435,14 @@ impl<'a> serialize::Encoder for Encoder<'a> { self.emit_enum_variant("None", 0, 0, |_| Ok(())) } fn emit_option_some(&mut self, f: F) -> EncodeResult - where F: FnOnce(&mut Encoder<'a>) -> EncodeResult + where F: FnOnce(&mut Self) -> EncodeResult { self.emit_enum_variant("Some", 1, 1, f) } fn emit_seq(&mut self, len: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Encoder<'a>) -> EncodeResult + where F: FnOnce(&mut Self) -> EncodeResult { if len == 0 { // empty vector optimization @@ -456,7 +456,7 @@ impl<'a> serialize::Encoder for Encoder<'a> { } fn emit_seq_elt(&mut self, _idx: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Encoder<'a>) -> EncodeResult + where F: FnOnce(&mut Self) -> EncodeResult { self.start_tag(EsVecElt as usize)?; @@ -465,7 +465,7 @@ impl<'a> serialize::Encoder for Encoder<'a> { } fn emit_map(&mut self, len: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Encoder<'a>) -> EncodeResult + where F: FnOnce(&mut Self) -> EncodeResult { if len == 0 { // empty map optimization @@ -479,7 +479,7 @@ impl<'a> serialize::Encoder for Encoder<'a> { } fn emit_map_elt_key(&mut self, _idx: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Encoder<'a>) -> EncodeResult + where F: FnOnce(&mut Self) -> EncodeResult { self.start_tag(EsMapKey as usize)?; @@ -488,7 +488,7 @@ impl<'a> serialize::Encoder for Encoder<'a> { } fn emit_map_elt_val(&mut self, _idx: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Encoder<'a>) -> EncodeResult + where F: FnOnce(&mut Self) -> EncodeResult { self.start_tag(EsMapVal as usize)?; f(self)?; diff --git a/src/librustc_metadata/tyencode.rs b/src/librustc_metadata/tyencode.rs index dbefd3eacc24a..73996518a1564 100644 --- a/src/librustc_metadata/tyencode.rs +++ b/src/librustc_metadata/tyencode.rs @@ -27,13 +27,11 @@ use rustc::hir; use syntax::abi::Abi; use syntax::ast; -use errors::Handler; use rbml::leb128; use encoder; pub struct ctxt<'a, 'tcx: 'a> { - pub diag: &'a Handler, // Def -> str Callback: pub ds: for<'b> fn(TyCtxt<'b, 'tcx, 'tcx>, DefId) -> String, // The type context. @@ -42,12 +40,11 @@ pub struct ctxt<'a, 'tcx: 'a> { } impl<'a, 'tcx> encoder::EncodeContext<'a, 'tcx> { - pub fn ty_str_ctxt<'b>(&'b self) -> ctxt<'b, 'tcx> { + pub fn ty_str_ctxt(&self) -> ctxt<'a, 'tcx> { ctxt { - diag: self.tcx.sess.diagnostic(), ds: encoder::def_to_string, tcx: self.tcx, - abbrevs: &self.type_abbrevs + abbrevs: self.type_abbrevs } } } From d47fd9eb5a6cb18ab1e11febcef04b0a919e8bcb Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Mon, 19 Sep 2016 23:46:31 +0300 Subject: [PATCH 07/39] rustc_metadata: use specialization for {en,de}coding Ty and Substs. --- src/librustc/middle/cstore.rs | 120 ++++----------------------- src/librustc/ty/mod.rs | 23 +---- src/librustc/ty/sty.rs | 4 +- src/librustc/ty/subst.rs | 24 +----- src/librustc_metadata/encoder.rs | 45 +++++++++- src/librustc_metadata/lib.rs | 1 + src/librustc_metadata/tls_context.rs | 22 +---- 7 files changed, 71 insertions(+), 168 deletions(-) diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index b2c293a290ab3..9dacb9062c1c3 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -509,85 +509,20 @@ pub trait MacroLoader { /// Note, however, that this only works for RBML-based encoding and decoding at /// the moment. pub mod tls { - use rbml::opaque::Encoder as OpaqueEncoder; use rbml::opaque::Decoder as OpaqueDecoder; - use serialize; use std::cell::Cell; - use std::mem; - use ty::{self, Ty, TyCtxt}; + use ty::{Ty, TyCtxt}; use ty::subst::Substs; use hir::def_id::DefId; - pub trait EncodingContext<'tcx> { - fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx>; - fn encode_ty(&self, encoder: &mut OpaqueEncoder, t: Ty<'tcx>); - fn encode_substs(&self, encoder: &mut OpaqueEncoder, substs: &Substs<'tcx>); - } - /// Marker type used for the TLS slot. /// The type context cannot be used directly because the TLS /// in libstd doesn't allow types generic over lifetimes. struct TlsPayload; - thread_local! { - static TLS_ENCODING: Cell> = Cell::new(None) - } - - /// Execute f after pushing the given EncodingContext onto the TLS stack. - pub fn enter_encoding_context<'tcx, F, R>(ecx: &EncodingContext<'tcx>, - encoder: &mut OpaqueEncoder, - f: F) -> R - where F: FnOnce(&EncodingContext<'tcx>, &mut OpaqueEncoder) -> R - { - let tls_payload = (ecx as *const _, encoder as *mut _); - let tls_ptr = &tls_payload as *const _ as *const TlsPayload; - TLS_ENCODING.with(|tls| { - let prev = tls.get(); - tls.set(Some(tls_ptr)); - let ret = f(ecx, encoder); - tls.set(prev); - return ret - }) - } - - /// Execute f with access to the thread-local encoding context and - /// rbml encoder. This function will panic if the encoder passed in and the - /// context encoder are not the same. - /// - /// Note that this method is 'practically' safe due to its checking that the - /// encoder passed in is the same as the one in TLS, but it would still be - /// possible to construct cases where the EncodingContext is exchanged - /// while the same encoder is used, thus working with a wrong context. - pub fn with_encoding_context<'tcx, E, F, R>(encoder: &mut E, f: F) -> R - where F: FnOnce(&EncodingContext<'tcx>, &mut OpaqueEncoder) -> R, - E: serialize::Encoder - { - unsafe { - unsafe_with_encoding_context(|ecx, tls_encoder| { - assert!(encoder as *mut _ as usize == tls_encoder as *mut _ as usize); - - let ecx: &EncodingContext<'tcx> = mem::transmute(ecx); - - f(ecx, tls_encoder) - }) - } - } - - /// Execute f with access to the thread-local encoding context and - /// rbml encoder. - pub unsafe fn unsafe_with_encoding_context(f: F) -> R - where F: FnOnce(&EncodingContext, &mut OpaqueEncoder) -> R - { - TLS_ENCODING.with(|tls| { - let tls = tls.get().unwrap(); - let tls_payload = tls as *mut (&EncodingContext, &mut OpaqueEncoder); - f((*tls_payload).0, (*tls_payload).1) - }) - } - pub trait DecodingContext<'tcx> { fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx>; - fn decode_ty(&self, decoder: &mut OpaqueDecoder) -> ty::Ty<'tcx>; + fn decode_ty(&self, decoder: &mut OpaqueDecoder) -> Ty<'tcx>; fn decode_substs(&self, decoder: &mut OpaqueDecoder) -> &'tcx Substs<'tcx>; fn translate_def_id(&self, def_id: DefId) -> DefId; } @@ -597,56 +532,31 @@ pub mod tls { } /// Execute f after pushing the given DecodingContext onto the TLS stack. - pub fn enter_decoding_context<'tcx, F, R>(dcx: &DecodingContext<'tcx>, - decoder: &mut OpaqueDecoder, - f: F) -> R - where F: FnOnce(&DecodingContext<'tcx>, &mut OpaqueDecoder) -> R + pub fn enter_decoding_context<'tcx, F, R>(dcx: &DecodingContext<'tcx>, f: F) -> R + where F: FnOnce(&DecodingContext<'tcx>) -> R { - let tls_payload = (dcx as *const _, decoder as *mut _); + let tls_payload = dcx as *const _; let tls_ptr = &tls_payload as *const _ as *const TlsPayload; TLS_DECODING.with(|tls| { let prev = tls.get(); tls.set(Some(tls_ptr)); - let ret = f(dcx, decoder); + let ret = f(dcx); tls.set(prev); - return ret + ret }) } - /// Execute f with access to the thread-local decoding context and - /// rbml decoder. This function will panic if the decoder passed in and the - /// context decoder are not the same. - /// - /// Note that this method is 'practically' safe due to its checking that the - /// decoder passed in is the same as the one in TLS, but it would still be - /// possible to construct cases where the DecodingContext is exchanged - /// while the same decoder is used, thus working with a wrong context. - pub fn with_decoding_context<'decoder, 'tcx, D, F, R>(d: &'decoder mut D, f: F) -> R - where D: serialize::Decoder, - F: FnOnce(&DecodingContext<'tcx>, - &mut OpaqueDecoder) -> R, - 'tcx: 'decoder + /// Execute f with access to the thread-local decoding context. + /// FIXME(eddyb) This is horribly unsound as it allows the + /// caler to pick any lifetime for 'tcx, including 'static. + pub fn with_decoding_context<'tcx, F, R>(f: F) -> R + where F: FnOnce(&DecodingContext<'tcx>) -> R, { unsafe { - unsafe_with_decoding_context(|dcx, decoder| { - assert!((d as *mut _ as usize) == (decoder as *mut _ as usize)); - - let dcx: &DecodingContext<'tcx> = mem::transmute(dcx); - - f(dcx, decoder) + TLS_DECODING.with(|tls| { + let tls = tls.get().unwrap(); + f(*(tls as *mut &DecodingContext)) }) } } - - /// Execute f with access to the thread-local decoding context and - /// rbml decoder. - pub unsafe fn unsafe_with_decoding_context(f: F) -> R - where F: FnOnce(&DecodingContext, &mut OpaqueDecoder) -> R - { - TLS_DECODING.with(|tls| { - let tls = tls.get().unwrap(); - let tls_payload = tls as *mut (&DecodingContext, &mut OpaqueDecoder); - f((*tls_payload).0, (*tls_payload).1) - }) - } } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 14eb2fb7914c3..716b4672ec72e 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -34,7 +34,7 @@ use util::common::MemoizationMap; use util::nodemap::NodeSet; use util::nodemap::FnvHashMap; -use serialize::{Encodable, Encoder, Decodable, Decoder}; +use serialize::{self, Encodable, Encoder, Decodable, Decoder}; use std::borrow::Cow; use std::cell::Cell; use std::hash::{Hash, Hasher}; @@ -567,23 +567,8 @@ impl<'tcx> Hash for TyS<'tcx> { pub type Ty<'tcx> = &'tcx TyS<'tcx>; -impl<'tcx> Encodable for Ty<'tcx> { - fn encode(&self, s: &mut S) -> Result<(), S::Error> { - cstore::tls::with_encoding_context(s, |ecx, rbml_w| { - ecx.encode_ty(rbml_w, *self); - Ok(()) - }) - } -} - -impl<'tcx> Decodable for Ty<'tcx> { - fn decode(d: &mut D) -> Result, D::Error> { - cstore::tls::with_decoding_context(d, |dcx, rbml_r| { - Ok(dcx.decode_ty(rbml_r)) - }) - } -} - +impl<'tcx> serialize::UseSpecializedEncodable for Ty<'tcx> {} +impl<'tcx> serialize::UseSpecializedDecodable for Ty<'tcx> {} /// Upvars do not get their own node-id. Instead, we use the pair of /// the original var id (that is, the root variable that is referenced @@ -1506,7 +1491,7 @@ impl<'tcx> Decodable for AdtDef<'tcx> { fn decode(d: &mut D) -> Result, D::Error> { let def_id: DefId = Decodable::decode(d)?; - cstore::tls::with_decoding_context(d, |dcx, _| { + cstore::tls::with_decoding_context(|dcx| { let def_id = dcx.translate_def_id(def_id); Ok(dcx.tcx().lookup_adt_def(def_id)) }) diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 5fdc7abc0af5b..5f02b1be44a82 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -275,7 +275,7 @@ impl<'tcx> Encodable for ClosureSubsts<'tcx> { impl<'tcx> Decodable for ClosureSubsts<'tcx> { fn decode(d: &mut D) -> Result, D::Error> { let (func_substs, upvar_tys) = Decodable::decode(d)?; - cstore::tls::with_decoding_context(d, |dcx, _| { + cstore::tls::with_decoding_context(|dcx| { Ok(ClosureSubsts { func_substs: func_substs, upvar_tys: dcx.tcx().mk_type_list(upvar_tys) @@ -666,7 +666,7 @@ pub enum Region { impl<'tcx> Decodable for &'tcx Region { fn decode(d: &mut D) -> Result<&'tcx Region, D::Error> { let r = Decodable::decode(d)?; - cstore::tls::with_decoding_context(d, |dcx, _| { + cstore::tls::with_decoding_context(|dcx| { Ok(dcx.tcx().mk_region(r)) }) } diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index 0ccfea2330999..6b493118bcfd0 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -10,12 +10,11 @@ // Type substitutions. -use middle::cstore; use hir::def_id::DefId; use ty::{self, Ty, TyCtxt}; use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; -use serialize::{Encodable, Encoder, Decodable, Decoder}; +use serialize; use syntax_pos::{Span, DUMMY_SP}; use core::nonzero::NonZero; @@ -298,25 +297,8 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx Substs<'tcx> { } } -impl<'tcx> Encodable for &'tcx Substs<'tcx> { - fn encode(&self, s: &mut S) -> Result<(), S::Error> { - cstore::tls::with_encoding_context(s, |ecx, rbml_w| { - ecx.encode_substs(rbml_w, self); - Ok(()) - }) - } -} - -impl<'tcx> Decodable for &'tcx Substs<'tcx> { - fn decode(d: &mut D) -> Result<&'tcx Substs<'tcx>, D::Error> { - let substs = cstore::tls::with_decoding_context(d, |dcx, rbml_r| { - dcx.decode_substs(rbml_r) - }); - - Ok(substs) - } -} - +impl<'tcx> serialize::UseSpecializedEncodable for &'tcx Substs<'tcx> {} +impl<'tcx> serialize::UseSpecializedDecodable for &'tcx Substs<'tcx> {} /////////////////////////////////////////////////////////////////////////// // Public trait `Subst` diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 4bc8caf037ae2..3b6984a8c4622 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -28,13 +28,14 @@ use middle::dependency_format::Linkage; use rustc::dep_graph::DepNode; use rustc::traits::specialization_graph; use rustc::ty::{self, Ty, TyCtxt}; +use rustc::ty::subst::Substs; use rustc::hir::svh::Svh; use rustc::mir::mir_map::MirMap; use rustc::session::config::{self, PanicStrategy, CrateTypeRustcMacro}; use rustc::util::nodemap::{FnvHashMap, NodeSet}; -use rustc_serialize::Encodable; +use rustc_serialize::{Encodable, SpecializedEncoder, SpecializedDecoder}; use std::cell::RefCell; use std::io::prelude::*; use std::io::{Cursor, SeekFrom}; @@ -78,6 +79,48 @@ impl<'a, 'tcx> DerefMut for EncodeContext<'a, 'tcx> { } } +impl<'a, 'tcx> SpecializedEncoder> for EncodeContext<'a, 'tcx> { + fn specialized_encode(&mut self, ty: &Ty<'tcx>) -> Result<(), Self::Error> { + let cx = self.ty_str_ctxt(); + self.emit_opaque(|opaque_encoder| { + Ok(tyencode::enc_ty(opaque_encoder.cursor, &cx, ty)) + }) + } +} + +impl<'a, 'tcx> SpecializedEncoder<&'tcx Substs<'tcx>> for EncodeContext<'a, 'tcx> { + fn specialized_encode(&mut self, substs: &&'tcx Substs<'tcx>) -> Result<(), Self::Error> { + let cx = self.ty_str_ctxt(); + self.emit_opaque(|opaque_encoder| { + Ok(tyencode::enc_substs(opaque_encoder.cursor, &cx, substs)) + }) + } +} + +/// FIXME(#31844) This is horribly unsound as it allows the +/// caller to pick any lifetime for 'tcx, including 'static. +impl<'a, 'tcx> SpecializedDecoder> for ::rbml::reader::Decoder<'a> { + fn specialized_decode(&mut self) -> Result, Self::Error> { + self.read_opaque(|opaque_decoder, _| { + ::middle::cstore::tls::with_decoding_context(|dcx| { + Ok(dcx.decode_ty(opaque_decoder)) + }) + }) + } +} + +/// FIXME(#31844) This is horribly unsound as it allows the +/// caller to pick any lifetime for 'tcx, including 'static. +impl<'a, 'tcx> SpecializedDecoder<&'tcx Substs<'tcx>> for ::rbml::reader::Decoder<'a> { + fn specialized_decode(&mut self) -> Result<&'tcx Substs<'tcx>, Self::Error> { + self.read_opaque(|opaque_decoder, _| { + ::middle::cstore::tls::with_decoding_context(|dcx| { + Ok(dcx.decode_substs(opaque_decoder)) + }) + }) + } +} + fn encode_name(ecx: &mut EncodeContext, name: Name) { ecx.wr_tagged_str(tag_paths_data_name, &name.as_str()); } diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs index d0d3d822f8605..d9d103beaf0f8 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -26,6 +26,7 @@ #![feature(rustc_macro_lib)] #![feature(rustc_macro_internals)] #![feature(rustc_private)] +#![feature(specialization)] #![feature(staged_api)] #![cfg_attr(test, feature(test))] diff --git a/src/librustc_metadata/tls_context.rs b/src/librustc_metadata/tls_context.rs index 6e78cbcd28e73..da6d04fc0ef37 100644 --- a/src/librustc_metadata/tls_context.rs +++ b/src/librustc_metadata/tls_context.rs @@ -11,32 +11,14 @@ // This module provides implementations for the thread-local encoding and // decoding context traits in rustc::middle::cstore::tls. -use rbml::opaque::Encoder as OpaqueEncoder; use rbml::opaque::Decoder as OpaqueDecoder; use rustc::middle::cstore::tls; use rustc::hir::def_id::DefId; use rustc::ty::subst::Substs; -use rustc::ty::{self, TyCtxt}; +use rustc::ty::{Ty, TyCtxt}; use decoder::{self, Cmd}; -use encoder; use tydecode::TyDecoder; -use tyencode; - -impl<'a, 'tcx: 'a> tls::EncodingContext<'tcx> for encoder::EncodeContext<'a, 'tcx> { - - fn tcx<'s>(&'s self) -> TyCtxt<'s, 'tcx, 'tcx> { - self.tcx - } - - fn encode_ty(&self, encoder: &mut OpaqueEncoder, t: ty::Ty<'tcx>) { - tyencode::enc_ty(encoder.cursor, &self.ty_str_ctxt(), t); - } - - fn encode_substs(&self, encoder: &mut OpaqueEncoder, substs: &Substs<'tcx>) { - tyencode::enc_substs(encoder.cursor, &self.ty_str_ctxt(), substs); - } -} pub struct DecodingContext<'a, 'tcx: 'a> { pub crate_metadata: Cmd<'a>, @@ -49,7 +31,7 @@ impl<'a, 'tcx: 'a> tls::DecodingContext<'tcx> for DecodingContext<'a, 'tcx> { self.tcx } - fn decode_ty(&self, decoder: &mut OpaqueDecoder) -> ty::Ty<'tcx> { + fn decode_ty(&self, decoder: &mut OpaqueDecoder) -> Ty<'tcx> { let def_id_convert = &mut |did| { decoder::translate_def_id(self.crate_metadata, did) }; From 3cbe4b8bce0fafb7b11895bb8b93ff6803fa8c03 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Tue, 30 Aug 2016 08:14:12 +0300 Subject: [PATCH 08/39] rustc_metadata: sign-extend when decoding signed integers. --- src/librustc_metadata/rbml/reader.rs | 67 +++++++++++++++++++++------- 1 file changed, 50 insertions(+), 17 deletions(-) diff --git a/src/librustc_metadata/rbml/reader.rs b/src/librustc_metadata/rbml/reader.rs index 0950372477e46..d4ac97ce5e03c 100644 --- a/src/librustc_metadata/rbml/reader.rs +++ b/src/librustc_metadata/rbml/reader.rs @@ -595,11 +595,9 @@ impl<'doc> Decoder<'doc> { } // variable-length unsigned integer with different tags. - // `first_tag` should be a tag for u8 or i8. - // `last_tag` should be the largest allowed integer tag with the matching signedness. + // `last_tag` should be the largest allowed unsigned integer tag. // all tags between them should be valid, in the order of u8, u16, u32 and u64. - fn _next_int(&mut self, - first_tag: EbmlEncoderTag, + fn next_uint(&mut self, last_tag: EbmlEncoderTag) -> DecodeResult { if self.pos >= self.parent.end { @@ -607,8 +605,8 @@ impl<'doc> Decoder<'doc> { } let TaggedDoc { tag: r_tag, doc: r_doc } = doc_at(self.parent.data, self.pos)?; - let r = if first_tag as usize <= r_tag && r_tag <= last_tag as usize { - match r_tag - first_tag as usize { + let r = if EsU8 as usize <= r_tag && r_tag <= last_tag as usize { + match r_tag - EsU8 as usize { 0 => doc_as_u8(r_doc) as u64, 1 => doc_as_u16(r_doc) as u64, 2 => doc_as_u32(r_doc) as u64, @@ -616,9 +614,8 @@ impl<'doc> Decoder<'doc> { _ => unreachable!(), } } else { - return Err(Expected(format!("expected EBML doc with tag {:?} through {:?} but \ + return Err(Expected(format!("expected EBML doc with tag EsU8 through {:?} but \ found tag {:?}", - first_tag, last_tag, r_tag))); }; @@ -629,7 +626,43 @@ impl<'doc> Decoder<'doc> { self.parent.end))); } self.pos = r_doc.end; - debug!("_next_int({:?}, {:?}) result={:?}", first_tag, last_tag, r); + debug!("next_uint({:?}) result={:?}", last_tag, r); + Ok(r) + } + + // variable-length signed integer with different tags. + // `last_tag` should be the largest allowed signed integer tag. + // all tags between them should be valid, in the order of i8, i16, i32 and i64. + fn next_int(&mut self, + last_tag: EbmlEncoderTag) + -> DecodeResult { + if self.pos >= self.parent.end { + return Err(Expected(format!("no more documents in current node!"))); + } + + let TaggedDoc { tag: r_tag, doc: r_doc } = doc_at(self.parent.data, self.pos)?; + let r = if EsI8 as usize <= r_tag && r_tag <= last_tag as usize { + match r_tag - EsI8 as usize { + 0 => doc_as_i8(r_doc) as i64, + 1 => doc_as_i16(r_doc) as i64, + 2 => doc_as_i32(r_doc) as i64, + 3 => doc_as_i64(r_doc), + _ => unreachable!(), + } + } else { + return Err(Expected(format!("expected EBML doc with tag EsI8 through {:?} but \ + found tag {:?}", + last_tag, + r_tag))); + }; + if r_doc.end > self.parent.end { + return Err(Expected(format!("invalid EBML, child extends to {:#x}, parent to \ + {:#x}", + r_doc.end, + self.parent.end))); + } + self.pos = r_doc.end; + debug!("next_int({:?}) result={:?}", last_tag, r); Ok(r) } @@ -662,19 +695,19 @@ impl<'doc> serialize::Decoder for Decoder<'doc> { } fn read_u64(&mut self) -> DecodeResult { - self._next_int(EsU8, EsU64) + self.next_uint(EsU64) } fn read_u32(&mut self) -> DecodeResult { - Ok(self._next_int(EsU8, EsU32)? as u32) + Ok(self.next_uint(EsU32)? as u32) } fn read_u16(&mut self) -> DecodeResult { - Ok(self._next_int(EsU8, EsU16)? as u16) + Ok(self.next_uint(EsU16)? as u16) } fn read_u8(&mut self) -> DecodeResult { Ok(doc_as_u8(self.next_doc(EsU8)?)) } fn read_usize(&mut self) -> DecodeResult { - let v = self._next_int(EsU8, EsU64)?; + let v = self.read_u64()?; if v > (::std::usize::MAX as u64) { Err(IntTooBig(v as usize)) } else { @@ -683,19 +716,19 @@ impl<'doc> serialize::Decoder for Decoder<'doc> { } fn read_i64(&mut self) -> DecodeResult { - Ok(self._next_int(EsI8, EsI64)? as i64) + Ok(self.next_int(EsI64)? as i64) } fn read_i32(&mut self) -> DecodeResult { - Ok(self._next_int(EsI8, EsI32)? as i32) + Ok(self.next_int(EsI32)? as i32) } fn read_i16(&mut self) -> DecodeResult { - Ok(self._next_int(EsI8, EsI16)? as i16) + Ok(self.next_int(EsI16)? as i16) } fn read_i8(&mut self) -> DecodeResult { Ok(doc_as_u8(self.next_doc(EsI8)?) as i8) } fn read_isize(&mut self) -> DecodeResult { - let v = self._next_int(EsI8, EsI64)? as i64; + let v = self.next_int(EsI64)? as i64; if v > (isize::MAX as i64) || v < (isize::MIN as i64) { debug!("FIXME \\#6122: Removing this makes this function miscompile"); Err(IntTooBig(v as usize)) From 97864d41a65d034fae21de35025e10151d765fef Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Tue, 30 Aug 2016 09:00:04 +0300 Subject: [PATCH 09/39] rustc_metadata: encode miscellaneous information opaquely. --- src/librustc_metadata/decoder.rs | 45 ++++++++-------------------- src/librustc_metadata/encoder.rs | 22 ++++++-------- src/librustc_metadata/rbml/reader.rs | 11 ++++--- src/librustc_metadata/rbml/writer.rs | 13 ++++---- 4 files changed, 32 insertions(+), 59 deletions(-) diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index ecddab0d0609e..b808aad143687 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -553,16 +553,14 @@ pub fn get_type<'a, 'tcx>(cdata: Cmd, id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) pub fn get_stability(cdata: Cmd, id: DefIndex) -> Option { let item = cdata.lookup_item(id); reader::maybe_get_doc(item, tag_items_data_item_stability).map(|doc| { - let mut decoder = reader::Decoder::new(doc); - Decodable::decode(&mut decoder).unwrap() + Decodable::decode(&mut doc.opaque()).unwrap() }) } pub fn get_deprecation(cdata: Cmd, id: DefIndex) -> Option { let item = cdata.lookup_item(id); reader::maybe_get_doc(item, tag_items_data_item_deprecation).map(|doc| { - let mut decoder = reader::Decoder::new(doc); - Decodable::decode(&mut decoder).unwrap() + Decodable::decode(&mut doc.opaque()).unwrap() }) } @@ -579,19 +577,12 @@ pub fn get_parent_impl(cdata: Cmd, id: DefIndex) -> Option { pub fn get_repr_attrs(cdata: Cmd, id: DefIndex) -> Vec { let item = cdata.lookup_item(id); - match reader::maybe_get_doc(item, tag_items_data_item_repr).map(|doc| { - let mut decoder = reader::Decoder::new(doc); - Decodable::decode(&mut decoder).unwrap() - }) { - Some(attrs) => attrs, - None => Vec::new(), - } + reader::maybe_get_doc(item, tag_items_data_item_repr).map_or(vec![], |doc| { + Decodable::decode(&mut doc.opaque()).unwrap() + }) } -pub fn get_impl_polarity<'tcx>(cdata: Cmd, - id: DefIndex) - -> Option -{ +pub fn get_impl_polarity(cdata: Cmd, id: DefIndex) -> Option { let item_doc = cdata.lookup_item(id); let fam = item_family(item_doc); match fam { @@ -602,15 +593,14 @@ pub fn get_impl_polarity<'tcx>(cdata: Cmd, } } -pub fn get_custom_coerce_unsized_kind<'tcx>( +pub fn get_custom_coerce_unsized_kind( cdata: Cmd, id: DefIndex) -> Option { let item_doc = cdata.lookup_item(id); reader::maybe_get_doc(item_doc, tag_impl_coerce_unsized_kind).map(|kind_doc| { - let mut decoder = reader::Decoder::new(kind_doc); - Decodable::decode(&mut decoder).unwrap() + Decodable::decode(&mut kind_doc.opaque()).unwrap() }) } @@ -989,8 +979,7 @@ pub fn get_trait_item_def_ids(cdata: Cmd, id: DefIndex) pub fn get_item_variances(cdata: Cmd, id: DefIndex) -> Vec { let item_doc = cdata.lookup_item(id); let variance_doc = reader::get_doc(item_doc, tag_item_variances); - let mut decoder = reader::Decoder::new(variance_doc); - Decodable::decode(&mut decoder).unwrap() + Decodable::decode(&mut variance_doc.opaque()).unwrap() } pub fn get_provided_trait_methods<'a, 'tcx>(cdata: Cmd, @@ -1109,10 +1098,7 @@ pub fn get_struct_field_names(cdata: Cmd, id: DefIndex) -> Vec { fn get_attributes(md: rbml::Doc) -> Vec { reader::maybe_get_doc(md, tag_attributes).map_or(vec![], |attrs_doc| { - let mut decoder = reader::Decoder::new(attrs_doc); - let mut attrs: Vec = decoder.read_opaque(|opaque_decoder, _| { - Decodable::decode(opaque_decoder) - }).unwrap(); + let mut attrs = Vec::::decode(&mut attrs_doc.opaque()).unwrap(); // Need new unique IDs: old thread-local IDs won't map to new threads. for attr in attrs.iter_mut() { @@ -1575,18 +1561,14 @@ pub fn get_imported_filemaps(metadata: &[u8]) -> Vec { let cm_doc = reader::get_doc(crate_doc, tag_codemap); reader::tagged_docs(cm_doc, tag_codemap_filemap).map(|filemap_doc| { - let mut decoder = reader::Decoder::new(filemap_doc); - decoder.read_opaque(|opaque_decoder, _| { - Decodable::decode(opaque_decoder) - }).unwrap() + Decodable::decode(&mut filemap_doc.opaque()).unwrap() }).collect() } pub fn closure_kind(cdata: Cmd, closure_id: DefIndex) -> ty::ClosureKind { let closure_doc = cdata.lookup_item(closure_id); let closure_kind_doc = reader::get_doc(closure_doc, tag_items_closure_kind); - let mut decoder = reader::Decoder::new(closure_kind_doc); - ty::ClosureKind::decode(&mut decoder).unwrap() + ty::ClosureKind::decode(&mut closure_kind_doc.opaque()).unwrap() } pub fn closure_ty<'a, 'tcx>(cdata: Cmd, closure_id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) @@ -1606,8 +1588,7 @@ pub fn def_key(cdata: Cmd, id: DefIndex) -> hir_map::DefKey { fn item_def_key(item_doc: rbml::Doc) -> hir_map::DefKey { match reader::maybe_get_doc(item_doc, tag_def_key) { Some(def_key_doc) => { - let mut decoder = reader::Decoder::new(def_key_doc); - let simple_key = def_key::DefKey::decode(&mut decoder).unwrap(); + let simple_key = def_key::DefKey::decode(&mut def_key_doc.opaque()).unwrap(); let name = reader::maybe_get_doc(item_doc, tag_paths_data_name).map(|name| { token::intern(name.as_str()).as_str() }); diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 3b6984a8c4622..3197d52e14d04 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -132,7 +132,7 @@ fn encode_def_id(ecx: &mut EncodeContext, id: DefId) { fn encode_def_key(ecx: &mut EncodeContext, key: DefKey) { let simple_key = def_key::simplify_def_key(key); ecx.start_tag(tag_def_key); - simple_key.encode(ecx); + simple_key.encode(&mut ecx.opaque()); ecx.end_tag(); } @@ -171,7 +171,7 @@ pub fn def_to_string(_tcx: TyCtxt, did: DefId) -> String { fn encode_item_variances(ecx: &mut EncodeContext, id: NodeId) { let v = ecx.tcx.item_variances(ecx.tcx.map.local_def_id(id)); ecx.start_tag(tag_item_variances); - v.encode(ecx); + v.encode(&mut ecx.opaque()); ecx.end_tag(); } @@ -786,7 +786,7 @@ impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { attr)); } self.start_tag(tag_items_data_item_repr); - repr_attrs.encode(self.ecx); + repr_attrs.encode(&mut self.opaque()); self.end_tag(); } @@ -821,7 +821,7 @@ fn encode_inherent_implementations(ecx: &mut EncodeContext, fn encode_stability(ecx: &mut EncodeContext, stab_opt: Option<&attr::Stability>) { stab_opt.map(|stab| { ecx.start_tag(tag_items_data_item_stability); - stab.encode(ecx).unwrap(); + stab.encode(&mut ecx.opaque()).unwrap(); ecx.end_tag(); }); } @@ -829,7 +829,7 @@ fn encode_stability(ecx: &mut EncodeContext, stab_opt: Option<&attr::Stability>) fn encode_deprecation(ecx: &mut EncodeContext, depr_opt: Option) { depr_opt.map(|depr| { ecx.start_tag(tag_items_data_item_deprecation); - depr.encode(ecx).unwrap(); + depr.encode(&mut ecx.opaque()).unwrap(); ecx.end_tag(); }); } @@ -1068,7 +1068,7 @@ impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { { Some(&kind) => { self.start_tag(tag_impl_coerce_unsized_kind); - kind.encode(self.ecx); + kind.encode(&mut self.opaque()); self.end_tag(); } None => {} @@ -1386,7 +1386,7 @@ impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { self.end_tag(); self.start_tag(tag_items_closure_kind); - tcx.closure_kind(def_id).encode(self.ecx).unwrap(); + tcx.closure_kind(def_id).encode(&mut self.opaque()).unwrap(); self.end_tag(); assert!(self.mir_map.map.contains_key(&def_id)); @@ -1428,9 +1428,7 @@ fn encode_item_index(ecx: &mut EncodeContext, index: IndexData) { fn encode_attributes(ecx: &mut EncodeContext, attrs: &[ast::Attribute]) { ecx.start_tag(tag_attributes); - ecx.emit_opaque(|opaque_encoder| { - attrs.encode(opaque_encoder) - }).unwrap(); + attrs.encode(&mut ecx.opaque()).unwrap(); ecx.end_tag(); } @@ -1565,9 +1563,7 @@ fn encode_codemap(ecx: &mut EncodeContext) { } ecx.start_tag(tag_codemap_filemap); - ecx.emit_opaque(|opaque_encoder| { - filemap.encode(opaque_encoder) - }).unwrap(); + filemap.encode(&mut ecx.opaque()).unwrap(); ecx.end_tag(); } diff --git a/src/librustc_metadata/rbml/reader.rs b/src/librustc_metadata/rbml/reader.rs index d4ac97ce5e03c..7878d8af98957 100644 --- a/src/librustc_metadata/rbml/reader.rs +++ b/src/librustc_metadata/rbml/reader.rs @@ -158,6 +158,10 @@ impl<'doc> Doc<'doc> { pub fn to_string(&self) -> String { self.as_str().to_string() } + + pub fn opaque(&self) -> opaque::Decoder<'doc> { + opaque::Decoder::new(self.data, self.start) + } } pub struct TaggedDoc<'a> { @@ -670,12 +674,7 @@ impl<'doc> Decoder<'doc> { where F: FnOnce(&mut opaque::Decoder, Doc) -> DecodeResult { let doc = self.next_doc(EsOpaque)?; - - let result = { - let mut opaque_decoder = opaque::Decoder::new(doc.data, doc.start); - op(&mut opaque_decoder, doc)? - }; - + let result = op(&mut doc.opaque(), doc)?; Ok(result) } diff --git a/src/librustc_metadata/rbml/writer.rs b/src/librustc_metadata/rbml/writer.rs index b49686e2379d6..db3a51187c60d 100644 --- a/src/librustc_metadata/rbml/writer.rs +++ b/src/librustc_metadata/rbml/writer.rs @@ -241,9 +241,7 @@ impl Encoder { } pos } -} -impl Encoder { // used internally to emit things like the vector length and so on fn _emit_tagged_sub(&mut self, v: usize) -> EncodeResult { if v as u8 as usize == v { @@ -256,16 +254,15 @@ impl Encoder { } } + pub fn opaque(&mut self) -> opaque::Encoder { + opaque::Encoder::new(&mut self.writer) + } + pub fn emit_opaque(&mut self, f: F) -> EncodeResult where F: FnOnce(&mut opaque::Encoder) -> EncodeResult { self.start_tag(EsOpaque as usize)?; - - { - let mut opaque_encoder = opaque::Encoder::new(&mut self.writer); - f(&mut opaque_encoder)?; - } - + f(&mut self.opaque())?; self.mark_stable_position(); self.end_tag() } From 91e7239db40372027a642bdbda19a6d593155a9f Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Tue, 30 Aug 2016 14:24:14 +0300 Subject: [PATCH 10/39] rustc_metadata: combine DecodeContext and rbml::reader::Decoder. --- src/librustc/middle/cstore.rs | 66 +--- src/librustc/middle/region.rs | 17 - src/librustc/ty/mod.rs | 16 +- src/librustc/ty/sty.rs | 32 +- src/librustc_metadata/astencode.rs | 478 +++++++-------------------- src/librustc_metadata/common.rs | 53 ++- src/librustc_metadata/decoder.rs | 122 ++++++- src/librustc_metadata/encoder.rs | 26 +- src/librustc_metadata/lib.rs | 4 - src/librustc_metadata/macros.rs | 46 --- src/librustc_metadata/rbml/reader.rs | 81 ++--- src/librustc_metadata/tls_context.rs | 84 ----- 12 files changed, 309 insertions(+), 716 deletions(-) delete mode 100644 src/librustc_metadata/macros.rs delete mode 100644 src/librustc_metadata/tls_context.rs diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 9dacb9062c1c3..c201c47ef5c40 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -495,68 +495,4 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { pub trait MacroLoader { fn load_crate(&mut self, extern_crate: &ast::Item, allows_macros: bool) -> Vec; -} - -/// Metadata encoding and decoding can make use of thread-local encoding and -/// decoding contexts. These allow implementers of serialize::Encodable and -/// Decodable to access information and datastructures that would otherwise not -/// be available to them. For example, we can automatically translate def-id and -/// span information during decoding because the decoding context knows which -/// crate the data is decoded from. Or it allows to make ty::Ty decodable -/// because the context has access to the TyCtxt that is needed for creating -/// ty::Ty instances. -/// -/// Note, however, that this only works for RBML-based encoding and decoding at -/// the moment. -pub mod tls { - use rbml::opaque::Decoder as OpaqueDecoder; - use std::cell::Cell; - use ty::{Ty, TyCtxt}; - use ty::subst::Substs; - use hir::def_id::DefId; - - /// Marker type used for the TLS slot. - /// The type context cannot be used directly because the TLS - /// in libstd doesn't allow types generic over lifetimes. - struct TlsPayload; - - pub trait DecodingContext<'tcx> { - fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx>; - fn decode_ty(&self, decoder: &mut OpaqueDecoder) -> Ty<'tcx>; - fn decode_substs(&self, decoder: &mut OpaqueDecoder) -> &'tcx Substs<'tcx>; - fn translate_def_id(&self, def_id: DefId) -> DefId; - } - - thread_local! { - static TLS_DECODING: Cell> = Cell::new(None) - } - - /// Execute f after pushing the given DecodingContext onto the TLS stack. - pub fn enter_decoding_context<'tcx, F, R>(dcx: &DecodingContext<'tcx>, f: F) -> R - where F: FnOnce(&DecodingContext<'tcx>) -> R - { - let tls_payload = dcx as *const _; - let tls_ptr = &tls_payload as *const _ as *const TlsPayload; - TLS_DECODING.with(|tls| { - let prev = tls.get(); - tls.set(Some(tls_ptr)); - let ret = f(dcx); - tls.set(prev); - ret - }) - } - - /// Execute f with access to the thread-local decoding context. - /// FIXME(eddyb) This is horribly unsound as it allows the - /// caler to pick any lifetime for 'tcx, including 'static. - pub fn with_decoding_context<'tcx, F, R>(f: F) -> R - where F: FnOnce(&DecodingContext<'tcx>) -> R, - { - unsafe { - TLS_DECODING.with(|tls| { - let tls = tls.get().unwrap(); - f(*(tls as *mut &DecodingContext)) - }) - } - } -} +} \ No newline at end of file diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index fb99820f7c855..33110c61e8f8b 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -20,7 +20,6 @@ use dep_graph::DepNode; use hir::map as ast_map; use session::Session; use util::nodemap::{FnvHashMap, NodeMap, NodeSet}; -use middle::cstore::InlinedItem; use ty; use std::cell::RefCell; @@ -1256,19 +1255,3 @@ pub fn resolve_crate(sess: &Session, map: &ast_map::Map) -> RegionMaps { } return maps; } - -pub fn resolve_inlined_item(sess: &Session, - region_maps: &RegionMaps, - item: &InlinedItem) { - let mut visitor = RegionResolutionVisitor { - sess: sess, - region_maps: region_maps, - cx: Context { - root_id: None, - parent: ROOT_CODE_EXTENT, - var_parent: ROOT_CODE_EXTENT - }, - terminating_scopes: NodeSet() - }; - item.visit(&mut visitor); -} diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 716b4672ec72e..c49094cb6881e 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -21,7 +21,7 @@ pub use self::fold::TypeFoldable; use dep_graph::{self, DepNode}; use hir::map as ast_map; use middle; -use middle::cstore::{self, LOCAL_CRATE}; +use middle::cstore::LOCAL_CRATE; use hir::def::{Def, PathResolution, ExportMap}; use hir::def_id::DefId; use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem}; @@ -34,7 +34,7 @@ use util::common::MemoizationMap; use util::nodemap::NodeSet; use util::nodemap::FnvHashMap; -use serialize::{self, Encodable, Encoder, Decodable, Decoder}; +use serialize::{self, Encodable, Encoder}; use std::borrow::Cow; use std::cell::Cell; use std::hash::{Hash, Hasher}; @@ -1487,17 +1487,7 @@ impl<'tcx> Encodable for AdtDef<'tcx> { } } -impl<'tcx> Decodable for AdtDef<'tcx> { - fn decode(d: &mut D) -> Result, D::Error> { - let def_id: DefId = Decodable::decode(d)?; - - cstore::tls::with_decoding_context(|dcx| { - let def_id = dcx.translate_def_id(def_id); - Ok(dcx.tcx().lookup_adt_def(def_id)) - }) - } -} - +impl<'tcx> serialize::UseSpecializedDecodable for AdtDef<'tcx> {} #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum AdtKind { Struct, Union, Enum } diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 5f02b1be44a82..5176fb665fbfb 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -10,7 +10,6 @@ //! This module contains TypeVariants and its major components -use middle::cstore; use hir::def_id::DefId; use middle::region; use ty::subst::Substs; @@ -25,7 +24,7 @@ use syntax::abi; use syntax::ast::{self, Name}; use syntax::parse::token::{keywords, InternedString}; -use serialize::{Decodable, Decoder, Encodable, Encoder}; +use serialize; use hir; @@ -253,7 +252,7 @@ pub enum TypeVariants<'tcx> { /// closure C wind up influencing the decisions we ought to make for /// closure C (which would then require fixed point iteration to /// handle). Plus it fixes an ICE. :P -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable)] pub struct ClosureSubsts<'tcx> { /// Lifetime and type parameters from the enclosing function. /// These are separated out because trans wants to pass them around @@ -266,23 +265,7 @@ pub struct ClosureSubsts<'tcx> { pub upvar_tys: &'tcx [Ty<'tcx>] } -impl<'tcx> Encodable for ClosureSubsts<'tcx> { - fn encode(&self, s: &mut S) -> Result<(), S::Error> { - (self.func_substs, self.upvar_tys).encode(s) - } -} - -impl<'tcx> Decodable for ClosureSubsts<'tcx> { - fn decode(d: &mut D) -> Result, D::Error> { - let (func_substs, upvar_tys) = Decodable::decode(d)?; - cstore::tls::with_decoding_context(|dcx| { - Ok(ClosureSubsts { - func_substs: func_substs, - upvar_tys: dcx.tcx().mk_type_list(upvar_tys) - }) - }) - } -} +impl<'tcx> serialize::UseSpecializedDecodable for ClosureSubsts<'tcx> {} #[derive(Clone, PartialEq, Eq, Hash)] pub struct TraitObject<'tcx> { @@ -663,14 +646,7 @@ pub enum Region { ReErased, } -impl<'tcx> Decodable for &'tcx Region { - fn decode(d: &mut D) -> Result<&'tcx Region, D::Error> { - let r = Decodable::decode(d)?; - cstore::tls::with_decoding_context(|dcx| { - Ok(dcx.tcx().mk_region(r)) - }) - } -} +impl<'tcx> serialize::UseSpecializedDecodable for &'tcx Region {} #[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)] pub struct EarlyBoundRegion { diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs index 3fd4d0cf27272..673a31c55abe0 100644 --- a/src/librustc_metadata/astencode.rs +++ b/src/librustc_metadata/astencode.rs @@ -13,7 +13,6 @@ #![allow(unused_must_use)] use rustc::hir::map as ast_map; -use rustc::session::Session; use rustc::hir; use rustc::hir::fold; @@ -23,9 +22,9 @@ use rustc::hir::intravisit::{Visitor, IdRangeComputingVisitor, IdRange}; use common as c; use cstore; use decoder; -use encoder as e; -use tydecode; -use tyencode; + +use decoder::DecodeContext; +use encoder::EncodeContext; use middle::cstore::{InlinedItem, InlinedItemRef}; use rustc::ty::adjustment; @@ -33,15 +32,12 @@ use rustc::ty::cast; use middle::const_qualif::ConstQualif; use rustc::hir::def::{self, Def}; use rustc::hir::def_id::DefId; -use middle::region; -use rustc::ty::subst::Substs; use rustc::ty::{self, Ty, TyCtxt}; use syntax::ast; use syntax::ptr::P; use syntax_pos; -use std::cell::Cell; use std::io::SeekFrom; use std::io::prelude::*; @@ -50,15 +46,6 @@ use rbml; use rustc_serialize::{Decodable, Decoder, DecoderHelpers}; use rustc_serialize::{Encodable, EncoderHelpers}; -struct DecodeContext<'a, 'tcx: 'a> { - tcx: TyCtxt<'a, 'tcx, 'tcx>, - cdata: &'a cstore::CrateMetadata, - from_id_range: IdRange, - to_id_range: IdRange, - // Cache the last used filemap for translating spans as an optimization. - last_filemap_index: Cell, -} - trait tr { fn tr(&self, dcx: &DecodeContext) -> Self; } @@ -66,7 +53,7 @@ trait tr { // ______________________________________________________________________ // Top-level methods. -pub fn encode_inlined_item(ecx: &mut e::EncodeContext, ii: InlinedItemRef) { +pub fn encode_inlined_item(ecx: &mut EncodeContext, ii: InlinedItemRef) { let id = match ii { InlinedItemRef::Item(_, i) => i.id, InlinedItemRef::TraitItem(_, ti) => ti.id, @@ -81,11 +68,16 @@ pub fn encode_inlined_item(ecx: &mut e::EncodeContext, ii: InlinedItemRef) { let id_range = inlined_item_id_range(&ii); assert_eq!(expected_id_range, id_range); - ecx.start_tag(c::tag_ast as usize); - id_range.encode(ecx); - ecx.start_tag(c::tag_tree as usize); - ecx.emit_opaque(|this| ii.encode(this)); + ecx.start_tag(c::tag_ast); + + ecx.start_tag(c::tag_id_range); + id_range.encode(&mut ecx.opaque()); ecx.end_tag(); + + ecx.start_tag(c::tag_tree); + ii.encode(ecx); + ecx.end_tag(); + encode_side_tables_for_ii(ecx, &ii); ecx.end_tag(); @@ -121,37 +113,27 @@ pub fn decode_inlined_item<'a, 'tcx>(cdata: &cstore::CrateMetadata, orig_did: DefId) -> &'tcx InlinedItem { debug!("> Decoding inlined fn: {:?}", tcx.item_path_str(orig_did)); - let mut ast_dsr = reader::Decoder::new(ast_doc); - let from_id_range = Decodable::decode(&mut ast_dsr).unwrap(); - let to_id_range = reserve_id_range(&tcx.sess, from_id_range); - let dcx = &DecodeContext { - cdata: cdata, - tcx: tcx, - from_id_range: from_id_range, - to_id_range: to_id_range, - last_filemap_index: Cell::new(0) - }; - let ii = ast_map::map_decoded_item(&dcx.tcx.map, + let id_range_doc = ast_doc.get(c::tag_id_range); + let from_id_range = IdRange::decode(&mut id_range_doc.opaque()).unwrap(); + let mut dcx = DecodeContext::new(tcx, cdata, from_id_range, + ast_doc.get(c::tag_tree)); + let ii = InlinedItem::decode(&mut dcx).unwrap(); + + let ii = ast_map::map_decoded_item(&tcx.map, parent_def_path, parent_did, - decode_ast(ast_doc), - dcx); - let name = match *ii { - InlinedItem::Item(_, ref i) => i.name, - InlinedItem::TraitItem(_, ref ti) => ti.name, - InlinedItem::ImplItem(_, ref ii) => ii.name + ii, + &dcx); + + let item_node_id = match ii { + &InlinedItem::Item(_, ref i) => i.id, + &InlinedItem::TraitItem(_, ref ti) => ti.id, + &InlinedItem::ImplItem(_, ref ii) => ii.id }; - debug!("Fn named: {}", name); - debug!("< Decoded inlined fn: {}::{}", - tcx.item_path_str(parent_did), - name); - region::resolve_inlined_item(&tcx.sess, &tcx.region_maps, ii); - decode_side_tables(dcx, ast_doc); - copy_item_types(dcx, ii, orig_did); - if let InlinedItem::Item(_, ref i) = *ii { - debug!(">>> DECODED ITEM >>>\n{}\n<<< DECODED ITEM <<<", - ::rustc::hir::print::item_to_string(&i)); - } + let inlined_did = tcx.map.local_def_id(item_node_id); + tcx.register_item_type(inlined_did, tcx.lookup_item_type(orig_did)); + + decode_side_tables(&mut dcx, ast_doc); ii } @@ -159,16 +141,6 @@ pub fn decode_inlined_item<'a, 'tcx>(cdata: &cstore::CrateMetadata, // ______________________________________________________________________ // Enumerating the IDs which appear in an AST -fn reserve_id_range(sess: &Session, - from_id_range: IdRange) -> IdRange { - // Handle the case of an empty range: - if from_id_range.empty() { return from_id_range; } - let cnt = from_id_range.max - from_id_range.min; - let to_id_min = sess.reserve_node_ids(cnt); - let to_id_max = to_id_min + cnt; - IdRange { min: to_id_min, max: to_id_max } -} - impl<'a, 'tcx> DecodeContext<'a, 'tcx> { /// Translates an internal id, meaning a node id that is known to refer to some part of the /// item currently being inlined, such as a local variable or argument. All naked node-ids @@ -312,20 +284,9 @@ fn simplify_ast(ii: InlinedItemRef) -> (InlinedItem, IdRange) { (ii, fld.id_range) } -fn decode_ast(item_doc: rbml::Doc) -> InlinedItem { - let chi_doc = item_doc.get(c::tag_tree as usize); - let mut rbml_r = reader::Decoder::new(chi_doc); - rbml_r.read_opaque(|decoder, _| Decodable::decode(decoder)).unwrap() -} - // ______________________________________________________________________ // Encoding and decoding of ast::def -fn decode_def(dcx: &DecodeContext, dsr: &mut reader::Decoder) -> Def { - let def: Def = Decodable::decode(dsr).unwrap(); - def.tr(dcx) -} - impl tr for Def { fn tr(&self, dcx: &DecodeContext) -> Def { match *self { @@ -378,11 +339,9 @@ impl tr for Def { // ______________________________________________________________________ // Encoding and decoding of freevar information -impl<'a> reader::Decoder<'a> { - fn read_freevar_entry(&mut self, dcx: &DecodeContext) - -> hir::Freevar { - let fv: hir::Freevar = Decodable::decode(self).unwrap(); - fv.tr(dcx) +impl<'a, 'tcx> DecodeContext<'a, 'tcx> { + fn read_freevar_entry(&mut self) -> hir::Freevar { + hir::Freevar::decode(self).unwrap().tr(self) } } @@ -398,7 +357,7 @@ impl tr for hir::Freevar { // ______________________________________________________________________ // Encoding and decoding of MethodCallee -impl<'a, 'tcx> e::EncodeContext<'a, 'tcx> { +impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn encode_method_callee(&mut self, autoderef: u32, method: &ty::MethodCallee<'tcx>) { @@ -412,31 +371,29 @@ impl<'a, 'tcx> e::EncodeContext<'a, 'tcx> { method.def_id.encode(this) }); this.emit_struct_field("ty", 2, |this| { - Ok(this.emit_ty(method.ty)) + method.ty.encode(this) }); this.emit_struct_field("substs", 3, |this| { - Ok(this.emit_substs(&method.substs)) + method.substs.encode(this) }) }).unwrap(); } } -impl<'a, 'tcx> reader::Decoder<'a> { - fn read_method_callee<'b>(&mut self, dcx: &DecodeContext<'b, 'tcx>) - -> (u32, ty::MethodCallee<'tcx>) { - +impl<'a, 'tcx> DecodeContext<'a, 'tcx> { + fn read_method_callee(&mut self) -> (u32, ty::MethodCallee<'tcx>) { self.read_struct("MethodCallee", 4, |this| { let autoderef = this.read_struct_field("autoderef", 0, Decodable::decode).unwrap(); Ok((autoderef, ty::MethodCallee { def_id: this.read_struct_field("def_id", 1, |this| { - DefId::decode(this).map(|d| d.tr(dcx)) + DefId::decode(this).map(|d| d.tr(this)) }).unwrap(), ty: this.read_struct_field("ty", 2, |this| { - Ok(this.read_ty(dcx)) + Ty::decode(this) }).unwrap(), substs: this.read_struct_field("substs", 3, |this| { - Ok(this.read_substs(dcx)) + Decodable::decode(this) }).unwrap() })) }).unwrap() @@ -446,21 +403,7 @@ impl<'a, 'tcx> reader::Decoder<'a> { // ______________________________________________________________________ // Encoding and decoding the side tables -impl<'a, 'tcx> e::EncodeContext<'a, 'tcx> { - fn emit_region(&mut self, r: &'tcx ty::Region) { - let cx = self.ty_str_ctxt(); - self.emit_opaque(|this| Ok(tyencode::enc_region(&mut this.cursor, - &cx, - r))); - } - - fn emit_ty(&mut self, ty: Ty<'tcx>) { - let cx = self.ty_str_ctxt(); - self.emit_opaque(|this| Ok(tyencode::enc_ty(&mut this.cursor, - &cx, - ty))); - } - +impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn emit_upvar_capture(&mut self, capture: &ty::UpvarCapture<'tcx>) { use rustc_serialize::Encoder; @@ -471,23 +414,14 @@ impl<'a, 'tcx> e::EncodeContext<'a, 'tcx> { } ty::UpvarCapture::ByRef(ty::UpvarBorrow { kind, region }) => { this.emit_enum_variant("ByRef", 2, 0, |this| { - this.emit_enum_variant_arg(0, - |this| kind.encode(this)); - this.emit_enum_variant_arg(1, - |this| Ok(this.emit_region(region))) + this.emit_enum_variant_arg(0, |this| kind.encode(this)); + this.emit_enum_variant_arg(1, |this| region.encode(this)) }) } } }).unwrap() } - fn emit_substs(&mut self, substs: &Substs<'tcx>) { - let cx = self.ty_str_ctxt(); - self.emit_opaque(|this| Ok(tyencode::enc_substs(&mut this.cursor, - &cx, - substs))); - } - fn emit_auto_adjustment(&mut self, adj: &adjustment::AutoAdjustment<'tcx>) { use rustc_serialize::Encoder; @@ -518,7 +452,7 @@ impl<'a, 'tcx> e::EncodeContext<'a, 'tcx> { adjustment::AdjustNeverToAny(ref ty) => { this.emit_enum_variant("AdjustNeverToAny", 5, 1, |this| { - this.emit_enum_variant_arg(0, |this| Ok(this.emit_ty(ty))) + this.emit_enum_variant_arg(0, |this| ty.encode(this)) }) } } @@ -532,8 +466,7 @@ impl<'a, 'tcx> e::EncodeContext<'a, 'tcx> { match autoref { &adjustment::AutoPtr(r, m) => { this.emit_enum_variant("AutoPtr", 0, 2, |this| { - this.emit_enum_variant_arg(0, - |this| Ok(this.emit_region(r))); + this.emit_enum_variant_arg(0, |this| r.encode(this)); this.emit_enum_variant_arg(1, |this| m.encode(this)) }) } @@ -562,24 +495,17 @@ impl<'a, 'tcx> e::EncodeContext<'a, 'tcx> { }); this.emit_struct_field("unsize", 2, |this| { - this.emit_option(|this| { - match auto_deref_ref.unsize { - None => this.emit_option_none(), - Some(target) => this.emit_option_some(|this| { - Ok(this.emit_ty(target)) - }) - } - }) + auto_deref_ref.unsize.encode(this) }) }); } fn tag(&mut self, - tag_id: c::astencode_tag, + tag_id: usize, f: F) where F: FnOnce(&mut Self), { - self.start_tag(tag_id as usize); + self.start_tag(tag_id); f(self); self.end_tag(); } @@ -590,7 +516,7 @@ impl<'a, 'tcx> e::EncodeContext<'a, 'tcx> { } struct SideTableEncodingIdVisitor<'a, 'b:'a, 'tcx:'b> { - ecx: &'a mut e::EncodeContext<'b, 'tcx>, + ecx: &'a mut EncodeContext<'b, 'tcx>, } impl<'a, 'b, 'tcx, 'v> Visitor<'v> for SideTableEncodingIdVisitor<'a, 'b, 'tcx> { @@ -599,15 +525,15 @@ impl<'a, 'b, 'tcx, 'v> Visitor<'v> for SideTableEncodingIdVisitor<'a, 'b, 'tcx> } } -fn encode_side_tables_for_ii(ecx: &mut e::EncodeContext, ii: &InlinedItem) { - ecx.start_tag(c::tag_table as usize); +fn encode_side_tables_for_ii(ecx: &mut EncodeContext, ii: &InlinedItem) { + ecx.start_tag(c::tag_table); ii.visit(&mut SideTableEncodingIdVisitor { ecx: ecx }); ecx.end_tag(); } -fn encode_side_tables_for_id(ecx: &mut e::EncodeContext, id: ast::NodeId) { +fn encode_side_tables_for_id(ecx: &mut EncodeContext, id: ast::NodeId) { let tcx = ecx.tcx; debug!("Encoding side tables for id {}", id); @@ -622,14 +548,14 @@ fn encode_side_tables_for_id(ecx: &mut e::EncodeContext, id: ast::NodeId) { if let Some(ty) = tcx.node_types().get(&id) { ecx.tag(c::tag_table_node_type, |ecx| { ecx.id(id); - ecx.emit_ty(*ty); + ty.encode(ecx); }) } if let Some(item_substs) = tcx.tables.borrow().item_substs.get(&id) { ecx.tag(c::tag_table_item_subst, |ecx| { ecx.id(id); - ecx.emit_substs(&item_substs.substs); + item_substs.substs.encode(ecx); }) } @@ -707,47 +633,8 @@ fn encode_side_tables_for_id(ecx: &mut e::EncodeContext, id: ast::NodeId) { } } -impl<'a, 'tcx> reader::Decoder<'a> { - fn read_ty_encoded<'b, F, R>(&mut self, dcx: &DecodeContext<'b, 'tcx>, op: F) -> R - where F: for<'x> FnOnce(&mut tydecode::TyDecoder<'x,'tcx>) -> R - { - return self.read_opaque(|_, doc| { - debug!("read_ty_encoded({})", type_string(doc)); - Ok(op( - &mut tydecode::TyDecoder::with_doc( - dcx.tcx, dcx.cdata.cnum, doc, - &mut |d| convert_def_id(dcx, d)))) - }).unwrap(); - - fn type_string(doc: rbml::Doc) -> String { - let mut str = String::new(); - for i in doc.start..doc.end { - str.push(doc.data[i] as char); - } - str - } - } - fn read_region<'b>(&mut self, dcx: &DecodeContext<'b, 'tcx>) -> &'tcx ty::Region { - // Note: regions types embed local node ids. In principle, we - // should translate these node ids into the new decode - // context. However, we do not bother, because region types - // are not used during trans. This also applies to read_ty. - return self.read_ty_encoded(dcx, |decoder| decoder.parse_region()); - } - fn read_ty<'b>(&mut self, dcx: &DecodeContext<'b, 'tcx>) -> Ty<'tcx> { - return self.read_ty_encoded(dcx, |decoder| decoder.parse_ty()); - } - - fn read_substs<'b>(&mut self, dcx: &DecodeContext<'b, 'tcx>) - -> &'tcx Substs<'tcx> { - self.read_opaque(|_, doc| { - Ok(tydecode::TyDecoder::with_doc(dcx.tcx, dcx.cdata.cnum, doc, - &mut |d| convert_def_id(dcx, d)) - .parse_substs()) - }).unwrap() - } - fn read_upvar_capture<'b>(&mut self, dcx: &DecodeContext<'b, 'tcx>) - -> ty::UpvarCapture<'tcx> { +impl<'a, 'tcx> DecodeContext<'a, 'tcx> { + fn read_upvar_capture(&mut self) -> ty::UpvarCapture<'tcx> { self.read_enum("UpvarCapture", |this| { let variants = ["ByValue", "ByRef"]; this.read_enum_variant(&variants, |this, i| { @@ -757,15 +644,14 @@ impl<'a, 'tcx> reader::Decoder<'a> { kind: this.read_enum_variant_arg(0, |this| Decodable::decode(this)).unwrap(), region: this.read_enum_variant_arg(1, - |this| Ok(this.read_region(dcx))).unwrap() + |this| Decodable::decode(this)).unwrap() }), _ => bug!("bad enum variant for ty::UpvarCapture") }) }) }).unwrap() } - fn read_auto_adjustment<'b>(&mut self, dcx: &DecodeContext<'b, 'tcx>) - -> adjustment::AutoAdjustment<'tcx> { + fn read_auto_adjustment(&mut self) -> adjustment::AutoAdjustment<'tcx> { self.read_enum("AutoAdjustment", |this| { let variants = ["AdjustReifyFnPointer", "AdjustUnsafeFnPointer", "AdjustMutToConstPointer", "AdjustDerefRef", @@ -778,13 +664,13 @@ impl<'a, 'tcx> reader::Decoder<'a> { 4 => { let auto_deref_ref: adjustment::AutoDerefRef = this.read_enum_variant_arg(0, - |this| Ok(this.read_auto_deref_ref(dcx))).unwrap(); + |this| Ok(this.read_auto_deref_ref())).unwrap(); adjustment::AdjustDerefRef(auto_deref_ref) } 5 => { let ty: Ty<'tcx> = this.read_enum_variant_arg(0, |this| { - Ok(this.read_ty(dcx)) + Ty::decode(this) }).unwrap(); adjustment::AdjustNeverToAny(ty) @@ -795,8 +681,7 @@ impl<'a, 'tcx> reader::Decoder<'a> { }).unwrap() } - fn read_auto_deref_ref<'b>(&mut self, dcx: &DecodeContext<'b, 'tcx>) - -> adjustment::AutoDerefRef<'tcx> { + fn read_auto_deref_ref(&mut self) -> adjustment::AutoDerefRef<'tcx> { self.read_struct("AutoDerefRef", 2, |this| { Ok(adjustment::AutoDerefRef { autoderefs: this.read_struct_field("autoderefs", 0, |this| { @@ -805,27 +690,20 @@ impl<'a, 'tcx> reader::Decoder<'a> { autoref: this.read_struct_field("autoref", 1, |this| { this.read_option(|this, b| { if b { - Ok(Some(this.read_autoref(dcx))) + Ok(Some(this.read_autoref())) } else { Ok(None) } }) }).unwrap(), unsize: this.read_struct_field("unsize", 2, |this| { - this.read_option(|this, b| { - if b { - Ok(Some(this.read_ty(dcx))) - } else { - Ok(None) - } - }) + Decodable::decode(this) }).unwrap(), }) }).unwrap() } - fn read_autoref<'b>(&mut self, dcx: &DecodeContext<'b, 'tcx>) - -> adjustment::AutoRef<'tcx> { + fn read_autoref(&mut self) -> adjustment::AutoRef<'tcx> { self.read_enum("AutoRef", |this| { let variants = ["AutoPtr", "AutoUnsafe"]; this.read_enum_variant(&variants, |this, i| { @@ -833,7 +711,7 @@ impl<'a, 'tcx> reader::Decoder<'a> { 0 => { let r: &'tcx ty::Region = this.read_enum_variant_arg(0, |this| { - Ok(this.read_region(dcx)) + Decodable::decode(this) }).unwrap(); let m: hir::Mutability = this.read_enum_variant_arg(1, |this| { @@ -853,183 +731,77 @@ impl<'a, 'tcx> reader::Decoder<'a> { }) }).unwrap() } - - fn read_cast_kind<'b>(&mut self, _dcx: &DecodeContext<'b, 'tcx>) - -> cast::CastKind - { - Decodable::decode(self).unwrap() - } } -// Converts a def-id that appears in a type. The correct -// translation will depend on what kind of def-id this is. -// This is a subtle point: type definitions are not -// inlined into the current crate, so if the def-id names -// a nominal type or type alias, then it should be -// translated to refer to the source crate. -// -// However, *type parameters* are cloned along with the function -// they are attached to. So we should translate those def-ids -// to refer to the new, cloned copy of the type parameter. -// We only see references to free type parameters in the body of -// an inlined function. In such cases, we need the def-id to -// be a local id so that the TypeContents code is able to lookup -// the relevant info in the ty_param_defs table. -// -// *Region parameters*, unfortunately, are another kettle of fish. -// In such cases, def_id's can appear in types to distinguish -// shadowed bound regions and so forth. It doesn't actually -// matter so much what we do to these, since regions are erased -// at trans time, but it's good to keep them consistent just in -// case. We translate them with `tr_def_id()` which will map -// the crate numbers back to the original source crate. -// -// Scopes will end up as being totally bogus. This can actually -// be fixed though. -// -// Unboxed closures are cloned along with the function being -// inlined, and all side tables use interned node IDs, so we -// translate their def IDs accordingly. -// -// It'd be really nice to refactor the type repr to not include -// def-ids so that all these distinctions were unnecessary. -fn convert_def_id(dcx: &DecodeContext, - did: DefId) - -> DefId { - let r = dcx.tr_def_id(did); - debug!("convert_def_id(did={:?})={:?}", did, r); - return r; -} +fn decode_side_tables<'a, 'tcx>(dcx: &mut DecodeContext<'a, 'tcx>, + ast_doc: rbml::Doc<'a>) { + for (tag, entry_doc) in reader::docs(ast_doc.get(c::tag_table)) { + dcx.rbml_r = reader::Decoder::new(entry_doc); -fn decode_side_tables(dcx: &DecodeContext, - ast_doc: rbml::Doc) { - let tbl_doc = ast_doc.get(c::tag_table as usize); - for (tag, entry_doc) in reader::docs(tbl_doc) { - let mut entry_dsr = reader::Decoder::new(entry_doc); - let id0: ast::NodeId = Decodable::decode(&mut entry_dsr).unwrap(); + let id0: ast::NodeId = Decodable::decode(dcx).unwrap(); let id = dcx.tr_id(id0); debug!(">> Side table document with tag 0x{:x} \ found for id {} (orig {})", tag, id, id0); - let tag = tag as u32; - let decoded_tag: Option = c::astencode_tag::from_u32(tag); - match decoded_tag { - None => { - bug!("unknown tag found in side tables: {:x}", tag); - } - Some(value) => { - let val_dsr = &mut entry_dsr; - match value { - c::tag_table_def => { - let def = decode_def(dcx, val_dsr); - dcx.tcx.def_map.borrow_mut().insert(id, def::PathResolution::new(def)); - } - c::tag_table_node_type => { - let ty = val_dsr.read_ty(dcx); - debug!("inserting ty for node {}: {:?}", - id, ty); - dcx.tcx.node_type_insert(id, ty); - } - c::tag_table_item_subst => { - let item_substs = ty::ItemSubsts { - substs: val_dsr.read_substs(dcx) - }; - dcx.tcx.tables.borrow_mut().item_substs.insert( - id, item_substs); - } - c::tag_table_freevars => { - let fv_info = val_dsr.read_to_vec(|val_dsr| { - Ok(val_dsr.read_freevar_entry(dcx)) - }).unwrap().into_iter().collect(); - dcx.tcx.freevars.borrow_mut().insert(id, fv_info); - } - c::tag_table_upvar_capture_map => { - let var_id: ast::NodeId = Decodable::decode(val_dsr).unwrap(); - let upvar_id = ty::UpvarId { - var_id: dcx.tr_id(var_id), - closure_expr_id: id - }; - let ub = val_dsr.read_upvar_capture(dcx); - dcx.tcx.tables.borrow_mut().upvar_capture_map.insert(upvar_id, ub); - } - c::tag_table_method_map => { - let (autoderef, method) = val_dsr.read_method_callee(dcx); - let method_call = ty::MethodCall { - expr_id: id, - autoderef: autoderef - }; - dcx.tcx.tables.borrow_mut().method_map.insert(method_call, method); - } - c::tag_table_adjustments => { - let adj = - val_dsr.read_auto_adjustment(dcx); - dcx.tcx.tables.borrow_mut().adjustments.insert(id, adj); - } - c::tag_table_cast_kinds => { - let cast_kind = - val_dsr.read_cast_kind(dcx); - dcx.tcx.cast_kinds.borrow_mut().insert(id, cast_kind); - } - c::tag_table_const_qualif => { - let qualif: ConstQualif = Decodable::decode(val_dsr).unwrap(); - dcx.tcx.const_qualif_map.borrow_mut().insert(id, qualif); - } - _ => { - bug!("unknown tag found in side tables: {:x}", tag); - } - } + match tag { + c::tag_table_def => { + let def = Def::decode(dcx).unwrap().tr(dcx); + dcx.tcx.def_map.borrow_mut().insert(id, def::PathResolution::new(def)); } - } - - debug!(">< Side table doc loaded"); - } -} - -// copy the tcache entries from the original item to the new -// inlined item -fn copy_item_types(dcx: &DecodeContext, ii: &InlinedItem, orig_did: DefId) { - fn copy_item_type(dcx: &DecodeContext, - inlined_id: ast::NodeId, - remote_did: DefId) { - let inlined_did = dcx.tcx.map.local_def_id(inlined_id); - dcx.tcx.register_item_type(inlined_did, - dcx.tcx.lookup_item_type(remote_did)); - - } - // copy the entry for the item itself - let item_node_id = match ii { - &InlinedItem::Item(_, ref i) => i.id, - &InlinedItem::TraitItem(_, ref ti) => ti.id, - &InlinedItem::ImplItem(_, ref ii) => ii.id - }; - copy_item_type(dcx, item_node_id, orig_did); - - // copy the entries of inner items - if let &InlinedItem::Item(_, ref item) = ii { - match item.node { - hir::ItemEnum(ref def, _) => { - let orig_def = dcx.tcx.lookup_adt_def(orig_did); - for (i_variant, orig_variant) in - def.variants.iter().zip(orig_def.variants.iter()) - { - debug!("astencode: copying variant {:?} => {:?}", - orig_variant.did, i_variant.node.data.id()); - copy_item_type(dcx, i_variant.node.data.id(), orig_variant.did); - } + c::tag_table_node_type => { + let ty = Ty::decode(dcx).unwrap(); + dcx.tcx.node_type_insert(id, ty); } - hir::ItemStruct(ref def, _) => { - if !def.is_struct() { - let ctor_did = dcx.tcx.lookup_adt_def(orig_did) - .struct_variant().did; - debug!("astencode: copying ctor {:?} => {:?}", ctor_did, - def.id()); - copy_item_type(dcx, def.id(), ctor_did); - } + c::tag_table_item_subst => { + let item_substs = ty::ItemSubsts { + substs: Decodable::decode(dcx).unwrap() + }; + dcx.tcx.tables.borrow_mut().item_substs.insert( + id, item_substs); + } + c::tag_table_freevars => { + let fv_info = dcx.read_to_vec(|dcx| { + Ok(dcx.read_freevar_entry()) + }).unwrap().into_iter().collect(); + dcx.tcx.freevars.borrow_mut().insert(id, fv_info); + } + c::tag_table_upvar_capture_map => { + let var_id = ast::NodeId::decode(dcx).unwrap(); + let upvar_id = ty::UpvarId { + var_id: dcx.tr_id(var_id), + closure_expr_id: id + }; + let ub = dcx.read_upvar_capture(); + dcx.tcx.tables.borrow_mut().upvar_capture_map.insert(upvar_id, ub); + } + c::tag_table_method_map => { + let (autoderef, method) = dcx.read_method_callee(); + let method_call = ty::MethodCall { + expr_id: id, + autoderef: autoderef + }; + dcx.tcx.tables.borrow_mut().method_map.insert(method_call, method); + } + c::tag_table_adjustments => { + let adj = dcx.read_auto_adjustment(); + dcx.tcx.tables.borrow_mut().adjustments.insert(id, adj); + } + c::tag_table_cast_kinds => { + let cast_kind = cast::CastKind::decode(dcx).unwrap(); + dcx.tcx.cast_kinds.borrow_mut().insert(id, cast_kind); + } + c::tag_table_const_qualif => { + let qualif = ConstQualif::decode(dcx).unwrap(); + dcx.tcx.const_qualif_map.borrow_mut().insert(id, qualif); + } + _ => { + bug!("unknown tag found in side tables: {:x}", tag); } - _ => {} } + + debug!(">< Side table doc loaded"); } } diff --git a/src/librustc_metadata/common.rs b/src/librustc_metadata/common.rs index 29b9cc0d1d923..c18b417466f94 100644 --- a/src/librustc_metadata/common.rs +++ b/src/librustc_metadata/common.rs @@ -10,8 +10,6 @@ #![allow(non_camel_case_types, non_upper_case_globals)] -pub use self::astencode_tag::*; - // RBML enum definitions and utils shared by the encoder and decoder // // 0x00..0x1f: reserved for RBML generic type tags @@ -97,33 +95,30 @@ pub const tag_items_data_item_reexport_def_id: usize = 0x47; pub const tag_items_data_item_reexport_name: usize = 0x48; // used to encode crate_ctxt side tables -enum_from_u32! { - #[derive(Copy, Clone, PartialEq)] - #[repr(usize)] - pub enum astencode_tag { // Reserves 0x50 -- 0x6f - tag_ast = 0x50, - - tag_tree = 0x51, - - tag_mir = 0x52, - - tag_table = 0x53, - // GAP 0x54, 0x55 - tag_table_def = 0x56, - tag_table_node_type = 0x57, - tag_table_item_subst = 0x58, - tag_table_freevars = 0x59, - // GAP 0x5a, 0x5b, 0x5c, 0x5d, 0x5e - tag_table_method_map = 0x5f, - // GAP 0x60 - tag_table_adjustments = 0x61, - // GAP 0x62, 0x63, 0x64, 0x65 - tag_table_upvar_capture_map = 0x66, - // GAP 0x67, 0x68 - tag_table_const_qualif = 0x69, - tag_table_cast_kinds = 0x6a, - } -} +pub const tag_ast: usize = 0x50; + +pub const tag_tree: usize = 0x51; + +pub const tag_mir: usize = 0x52; + +pub const tag_table: usize = 0x53; + +pub const tag_id_range: usize = 0x54; + +// GAP 0x55 +pub const tag_table_def: usize = 0x56; +pub const tag_table_node_type: usize = 0x57; +pub const tag_table_item_subst: usize = 0x58; +pub const tag_table_freevars: usize = 0x59; +// GAP 0x5a, 0x5b, 0x5c, 0x5d, 0x5e +pub const tag_table_method_map: usize = 0x5f; +// GAP 0x60 +pub const tag_table_adjustments: usize = 0x61; +// GAP 0x62, 0x63, 0x64, 0x65 +pub const tag_table_upvar_capture_map: usize = 0x66; +// GAP 0x67, 0x68 +pub const tag_table_const_qualif: usize = 0x69; +pub const tag_table_cast_kinds: usize = 0x6a; pub const tag_item_trait_item_sort: usize = 0x70; diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index b808aad143687..10c2747ab1696 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -20,7 +20,6 @@ use common::*; use def_key; use encoder::def_to_u64; use index; -use tls_context; use tydecode::TyDecoder; use rustc::hir::def_id::CRATE_DEF_INDEX; @@ -29,15 +28,17 @@ use rustc::hir::map as hir_map; use rustc::hir::map::DefKey; use rustc::util::nodemap::FnvHashMap; use rustc::hir; +use rustc::hir::intravisit::IdRange; use rustc::session::config::PanicStrategy; use middle::cstore::{InlinedItem, LinkagePreference}; -use middle::cstore::{DefLike, DlDef, DlField, DlImpl, tls}; +use middle::cstore::{DefLike, DlDef, DlField, DlImpl}; use rustc::hir::def::Def; use rustc::hir::def_id::{DefId, DefIndex}; use middle::lang_items; use rustc::ty::{ImplContainer, TraitContainer}; use rustc::ty::{self, AdtKind, Ty, TyCtxt, TypeFoldable, VariantKind}; +use rustc::ty::subst::Substs; use rustc_const_math::ConstInt; @@ -47,12 +48,13 @@ use rustc::mir::repr::Location; use std::cell::Cell; use std::io; +use std::ops::{Deref, DerefMut}; use std::rc::Rc; use std::str; use rbml::reader; use rbml; -use rustc_serialize::Decodable; +use rustc_serialize::{Decodable, Decoder, SpecializedDecoder}; use syntax::attr; use syntax::parse::token; use syntax::ast; @@ -60,6 +62,106 @@ use syntax::codemap; use syntax::print::pprust; use syntax_pos::{self, Span, BytePos, NO_EXPANSION}; +pub struct DecodeContext<'a, 'tcx: 'a> { + pub rbml_r: rbml::reader::Decoder<'a>, + pub tcx: TyCtxt<'a, 'tcx, 'tcx>, + pub cdata: &'a cstore::CrateMetadata, + pub from_id_range: IdRange, + pub to_id_range: IdRange, + // Cache the last used filemap for translating spans as an optimization. + pub last_filemap_index: Cell, +} + +impl<'a, 'tcx> DecodeContext<'a, 'tcx> { + pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, + cdata: &'a cstore::CrateMetadata, + from_id_range: IdRange, + doc: rbml::Doc<'a>) + -> DecodeContext<'a, 'tcx> { + // Handle the case of an empty range: + let to_id_range = if from_id_range.empty() { + from_id_range + } else { + let cnt = from_id_range.max - from_id_range.min; + let to_id_min = tcx.sess.reserve_node_ids(cnt); + let to_id_max = to_id_min + cnt; + IdRange { min: to_id_min, max: to_id_max } + }; + + DecodeContext { + rbml_r: reader::Decoder::new(doc), + cdata: cdata, + tcx: tcx, + from_id_range: from_id_range, + to_id_range: to_id_range, + last_filemap_index: Cell::new(0) + } + } + + fn read_ty_encoded(&mut self, op: F) -> R + where F: for<'x> FnOnce(&mut TyDecoder<'x,'tcx>) -> R + { + self.read_opaque(|this, doc| { + Ok(op(&mut TyDecoder::with_doc( + this.tcx, this.cdata.cnum, doc, + &mut |d| this.tr_def_id(d)))) + }).unwrap() + } +} + +impl<'a, 'tcx> Deref for DecodeContext<'a, 'tcx> { + type Target = rbml::reader::Decoder<'a>; + fn deref(&self) -> &Self::Target { + &self.rbml_r + } +} + +impl<'a, 'tcx> DerefMut for DecodeContext<'a, 'tcx> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.rbml_r + } +} + +// FIXME(#36588) These impls are horribly unsound as they allow +// the caller to pick any lifetime for 'tcx, including 'static, +// by using the unspecialized proxies to them. + +impl<'a, 'tcx> SpecializedDecoder> for DecodeContext<'a, 'tcx> { + fn specialized_decode(&mut self) -> Result, Self::Error> { + Ok(self.read_ty_encoded(|d| d.parse_ty())) + } +} + +impl<'a, 'tcx> SpecializedDecoder<&'tcx Substs<'tcx>> for DecodeContext<'a, 'tcx> { + fn specialized_decode(&mut self) -> Result<&'tcx Substs<'tcx>, Self::Error> { + Ok(self.read_ty_encoded(|d| d.parse_substs())) + } +} + +impl<'a, 'tcx> SpecializedDecoder<&'tcx ty::Region> for DecodeContext<'a, 'tcx> { + fn specialized_decode(&mut self) -> Result<&'tcx ty::Region, Self::Error> { + let r = ty::Region::decode(self)?; + Ok(self.tcx.mk_region(r)) + } +} + +impl<'a, 'tcx> SpecializedDecoder> for DecodeContext<'a, 'tcx> { + fn specialized_decode(&mut self) -> Result, Self::Error> { + Ok(ty::ClosureSubsts { + func_substs: Decodable::decode(this)?, + upvar_tys: this.tcx.mk_type_list(Decodable::decode(this)?) + }) + } +} + +impl<'a, 'tcx> SpecializedDecoder> for DecodeContext<'a, 'tcx> { + fn specialized_decode(&mut self) -> Result, Self::Error> { + let def_id = DefId::decode(self)?; + let def_id = translate_def_id(self.cdata, def_id); + Ok(self.tcx.lookup_adt_def(def_id)) + } +} + pub type Cmd<'a> = &'a CrateMetadata; impl CrateMetadata { @@ -796,17 +898,13 @@ pub fn maybe_get_item_mir<'a, 'tcx>(cdata: Cmd, let item_doc = cdata.lookup_item(id); return reader::maybe_get_doc(item_doc, tag_mir as usize).map(|mir_doc| { - let dcx = tls_context::DecodingContext { - crate_metadata: cdata, - tcx: tcx, - }; - let mut decoder = reader::Decoder::new(mir_doc); + let mut dcx = DecodeContext::new(tcx, cdata, + IdRange { min: 0, max: 0 }, + mir_doc); - let mut mir = tls::enter_decoding_context(&dcx, |_| { - Decodable::decode(&mut decoder) - }).unwrap(); + let mut mir = Decodable::decode(&mut dcx).unwrap(); - assert!(decoder.position() == mir_doc.end); + assert!(dcx.rbml_r.position() == mir_doc.end); let mut def_id_and_span_translator = MirDefIdAndSpanTranslator { crate_metadata: cdata, diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 3197d52e14d04..0f7765713c3c9 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -35,7 +35,7 @@ use rustc::mir::mir_map::MirMap; use rustc::session::config::{self, PanicStrategy, CrateTypeRustcMacro}; use rustc::util::nodemap::{FnvHashMap, NodeSet}; -use rustc_serialize::{Encodable, SpecializedEncoder, SpecializedDecoder}; +use rustc_serialize::{Encodable, SpecializedEncoder}; use std::cell::RefCell; use std::io::prelude::*; use std::io::{Cursor, SeekFrom}; @@ -97,30 +97,6 @@ impl<'a, 'tcx> SpecializedEncoder<&'tcx Substs<'tcx>> for EncodeContext<'a, 'tcx } } -/// FIXME(#31844) This is horribly unsound as it allows the -/// caller to pick any lifetime for 'tcx, including 'static. -impl<'a, 'tcx> SpecializedDecoder> for ::rbml::reader::Decoder<'a> { - fn specialized_decode(&mut self) -> Result, Self::Error> { - self.read_opaque(|opaque_decoder, _| { - ::middle::cstore::tls::with_decoding_context(|dcx| { - Ok(dcx.decode_ty(opaque_decoder)) - }) - }) - } -} - -/// FIXME(#31844) This is horribly unsound as it allows the -/// caller to pick any lifetime for 'tcx, including 'static. -impl<'a, 'tcx> SpecializedDecoder<&'tcx Substs<'tcx>> for ::rbml::reader::Decoder<'a> { - fn specialized_decode(&mut self) -> Result<&'tcx Substs<'tcx>, Self::Error> { - self.read_opaque(|opaque_decoder, _| { - ::middle::cstore::tls::with_decoding_context(|dcx| { - Ok(dcx.decode_substs(opaque_decoder)) - }) - }) - } -} - fn encode_name(ecx: &mut EncodeContext, name: Name) { ecx.wr_tagged_str(tag_paths_data_name, &name.as_str()); } diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs index d9d103beaf0f8..428b33f2bfa66 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -61,9 +61,6 @@ pub mod rbml { pub use rustc::middle; -#[macro_use] -mod macros; - pub mod diagnostics; pub mod astencode; @@ -80,6 +77,5 @@ pub mod cstore; pub mod index; pub mod loader; pub mod macro_import; -pub mod tls_context; __build_diagnostic_array! { librustc_metadata, DIAGNOSTICS } diff --git a/src/librustc_metadata/macros.rs b/src/librustc_metadata/macros.rs deleted file mode 100644 index ed764ebd9f95d..0000000000000 --- a/src/librustc_metadata/macros.rs +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -macro_rules! enum_from_u32 { - ($(#[$attr:meta])* pub enum $name:ident { - $($variant:ident = $e:expr,)* - }) => { - $(#[$attr])* - pub enum $name { - $($variant = $e),* - } - - impl $name { - pub fn from_u32(u: u32) -> Option<$name> { - $(if u == $name::$variant as u32 { - return Some($name::$variant) - })* - None - } - } - }; - ($(#[$attr:meta])* pub enum $name:ident { - $($variant:ident,)* - }) => { - $(#[$attr])* - pub enum $name { - $($variant,)* - } - - impl $name { - pub fn from_u32(u: u32) -> Option<$name> { - $(if u == $name::$variant as u32 { - return Some($name::$variant) - })* - None - } - } - } -} diff --git a/src/librustc_metadata/rbml/reader.rs b/src/librustc_metadata/rbml/reader.rs index 7878d8af98957..02acfef612a19 100644 --- a/src/librustc_metadata/rbml/reader.rs +++ b/src/librustc_metadata/rbml/reader.rs @@ -555,20 +555,6 @@ impl<'doc> Decoder<'doc> { Ok(r_doc) } - fn push_doc(&mut self, exp_tag: EbmlEncoderTag, f: F) -> DecodeResult - where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult - { - let d = self.next_doc(exp_tag)?; - let old_parent = self.parent; - let old_pos = self.pos; - self.parent = d; - self.pos = d.start; - let r = f(self)?; - self.parent = old_parent; - self.pos = old_pos; - Ok(r) - } - fn _next_sub(&mut self) -> DecodeResult { // empty vector/map optimization if self.parent.is_empty() { @@ -670,14 +656,6 @@ impl<'doc> Decoder<'doc> { Ok(r) } - pub fn read_opaque(&mut self, op: F) -> DecodeResult - where F: FnOnce(&mut opaque::Decoder, Doc) -> DecodeResult - { - let doc = self.next_doc(EsOpaque)?; - let result = op(&mut doc.opaque(), doc)?; - Ok(result) - } - pub fn position(&self) -> usize { self.pos } @@ -687,7 +665,30 @@ impl<'doc> Decoder<'doc> { } } -impl<'doc> serialize::Decoder for Decoder<'doc> { +impl<'doc, 'tcx> ::decoder::DecodeContext<'doc, 'tcx> { + pub fn read_opaque(&mut self, op: F) -> DecodeResult + where F: FnOnce(&mut Self, Doc) -> DecodeResult + { + let doc = self.next_doc(EsOpaque)?; + op(self, doc) + } + + fn push_doc(&mut self, exp_tag: EbmlEncoderTag, f: F) -> DecodeResult + where F: FnOnce(&mut Self) -> DecodeResult + { + let d = self.next_doc(exp_tag)?; + let old_parent = self.parent; + let old_pos = self.pos; + self.parent = d; + self.pos = d.start; + let r = f(self)?; + self.parent = old_parent; + self.pos = old_pos; + Ok(r) + } +} + +impl<'doc, 'tcx> serialize::Decoder for ::decoder::DecodeContext<'doc, 'tcx> { type Error = Error; fn read_nil(&mut self) -> DecodeResult<()> { Ok(()) @@ -757,7 +758,7 @@ impl<'doc> serialize::Decoder for Decoder<'doc> { // Compound types: fn read_enum(&mut self, name: &str, f: F) -> DecodeResult - where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult + where F: FnOnce(&mut Self) -> DecodeResult { debug!("read_enum({})", name); @@ -775,7 +776,7 @@ impl<'doc> serialize::Decoder for Decoder<'doc> { } fn read_enum_variant(&mut self, _: &[&str], mut f: F) -> DecodeResult - where F: FnMut(&mut Decoder<'doc>, usize) -> DecodeResult + where F: FnMut(&mut Self, usize) -> DecodeResult { debug!("read_enum_variant()"); let idx = self._next_sub()?; @@ -785,14 +786,14 @@ impl<'doc> serialize::Decoder for Decoder<'doc> { } fn read_enum_variant_arg(&mut self, idx: usize, f: F) -> DecodeResult - where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult + where F: FnOnce(&mut Self) -> DecodeResult { debug!("read_enum_variant_arg(idx={})", idx); f(self) } fn read_enum_struct_variant(&mut self, _: &[&str], mut f: F) -> DecodeResult - where F: FnMut(&mut Decoder<'doc>, usize) -> DecodeResult + where F: FnMut(&mut Self, usize) -> DecodeResult { debug!("read_enum_struct_variant()"); let idx = self._next_sub()?; @@ -806,28 +807,28 @@ impl<'doc> serialize::Decoder for Decoder<'doc> { idx: usize, f: F) -> DecodeResult - where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult + where F: FnOnce(&mut Self) -> DecodeResult { debug!("read_enum_struct_variant_arg(name={}, idx={})", name, idx); f(self) } fn read_struct(&mut self, name: &str, _: usize, f: F) -> DecodeResult - where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult + where F: FnOnce(&mut Self) -> DecodeResult { debug!("read_struct(name={})", name); f(self) } fn read_struct_field(&mut self, name: &str, idx: usize, f: F) -> DecodeResult - where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult + where F: FnOnce(&mut Self) -> DecodeResult { debug!("read_struct_field(name={}, idx={})", name, idx); f(self) } fn read_tuple(&mut self, tuple_len: usize, f: F) -> DecodeResult - where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult + where F: FnOnce(&mut Self) -> DecodeResult { debug!("read_tuple()"); self.read_seq(move |d, len| { @@ -843,28 +844,28 @@ impl<'doc> serialize::Decoder for Decoder<'doc> { } fn read_tuple_arg(&mut self, idx: usize, f: F) -> DecodeResult - where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult + where F: FnOnce(&mut Self) -> DecodeResult { debug!("read_tuple_arg(idx={})", idx); self.read_seq_elt(idx, f) } fn read_tuple_struct(&mut self, name: &str, len: usize, f: F) -> DecodeResult - where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult + where F: FnOnce(&mut Self) -> DecodeResult { debug!("read_tuple_struct(name={})", name); self.read_tuple(len, f) } fn read_tuple_struct_arg(&mut self, idx: usize, f: F) -> DecodeResult - where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult + where F: FnOnce(&mut Self) -> DecodeResult { debug!("read_tuple_struct_arg(idx={})", idx); self.read_tuple_arg(idx, f) } fn read_option(&mut self, mut f: F) -> DecodeResult - where F: FnMut(&mut Decoder<'doc>, bool) -> DecodeResult + where F: FnMut(&mut Self, bool) -> DecodeResult { debug!("read_option()"); self.read_enum("Option", move |this| { @@ -879,7 +880,7 @@ impl<'doc> serialize::Decoder for Decoder<'doc> { } fn read_seq(&mut self, f: F) -> DecodeResult - where F: FnOnce(&mut Decoder<'doc>, usize) -> DecodeResult + where F: FnOnce(&mut Self, usize) -> DecodeResult { debug!("read_seq()"); self.push_doc(EsVec, move |d| { @@ -890,14 +891,14 @@ impl<'doc> serialize::Decoder for Decoder<'doc> { } fn read_seq_elt(&mut self, idx: usize, f: F) -> DecodeResult - where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult + where F: FnOnce(&mut Self) -> DecodeResult { debug!("read_seq_elt(idx={})", idx); self.push_doc(EsVecElt, f) } fn read_map(&mut self, f: F) -> DecodeResult - where F: FnOnce(&mut Decoder<'doc>, usize) -> DecodeResult + where F: FnOnce(&mut Self, usize) -> DecodeResult { debug!("read_map()"); self.push_doc(EsMap, move |d| { @@ -908,14 +909,14 @@ impl<'doc> serialize::Decoder for Decoder<'doc> { } fn read_map_elt_key(&mut self, idx: usize, f: F) -> DecodeResult - where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult + where F: FnOnce(&mut Self) -> DecodeResult { debug!("read_map_elt_key(idx={})", idx); self.push_doc(EsMapKey, f) } fn read_map_elt_val(&mut self, idx: usize, f: F) -> DecodeResult - where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult + where F: FnOnce(&mut Self) -> DecodeResult { debug!("read_map_elt_val(idx={})", idx); self.push_doc(EsMapVal, f) diff --git a/src/librustc_metadata/tls_context.rs b/src/librustc_metadata/tls_context.rs deleted file mode 100644 index da6d04fc0ef37..0000000000000 --- a/src/librustc_metadata/tls_context.rs +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// This module provides implementations for the thread-local encoding and -// decoding context traits in rustc::middle::cstore::tls. - -use rbml::opaque::Decoder as OpaqueDecoder; -use rustc::middle::cstore::tls; -use rustc::hir::def_id::DefId; -use rustc::ty::subst::Substs; -use rustc::ty::{Ty, TyCtxt}; - -use decoder::{self, Cmd}; -use tydecode::TyDecoder; - -pub struct DecodingContext<'a, 'tcx: 'a> { - pub crate_metadata: Cmd<'a>, - pub tcx: TyCtxt<'a, 'tcx, 'tcx>, -} - -impl<'a, 'tcx: 'a> tls::DecodingContext<'tcx> for DecodingContext<'a, 'tcx> { - - fn tcx<'s>(&'s self) -> TyCtxt<'s, 'tcx, 'tcx> { - self.tcx - } - - fn decode_ty(&self, decoder: &mut OpaqueDecoder) -> Ty<'tcx> { - let def_id_convert = &mut |did| { - decoder::translate_def_id(self.crate_metadata, did) - }; - - let starting_position = decoder.position(); - - let mut ty_decoder = TyDecoder::new( - self.crate_metadata.data.as_slice(), - self.crate_metadata.cnum, - starting_position, - self.tcx, - def_id_convert); - - let ty = ty_decoder.parse_ty(); - - let end_position = ty_decoder.position(); - - // We can just reuse the tydecode implementation for parsing types, but - // we have to make sure to leave the rbml reader at the position just - // after the type. - decoder.advance(end_position - starting_position); - ty - } - - fn decode_substs(&self, decoder: &mut OpaqueDecoder) -> &'tcx Substs<'tcx> { - let def_id_convert = &mut |did| { - decoder::translate_def_id(self.crate_metadata, did) - }; - - let starting_position = decoder.position(); - - let mut ty_decoder = TyDecoder::new( - self.crate_metadata.data.as_slice(), - self.crate_metadata.cnum, - starting_position, - self.tcx, - def_id_convert); - - let substs = ty_decoder.parse_substs(); - - let end_position = ty_decoder.position(); - - decoder.advance(end_position - starting_position); - substs - } - - fn translate_def_id(&self, def_id: DefId) -> DefId { - decoder::translate_def_id(self.crate_metadata, def_id) - } -} From fc363cb482f92851b48b46402b5b5117627a840e Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Wed, 31 Aug 2016 14:00:29 +0300 Subject: [PATCH 11/39] rustc_metadata: go only through rustc_serialize in astencode. --- src/librustc/hir/def_id.rs | 54 +- src/librustc/hir/intravisit.rs | 6 +- src/librustc/hir/lowering.rs | 18 +- src/librustc/hir/map/collector.rs | 6 +- src/librustc/hir/map/definitions.rs | 7 +- src/librustc/hir/map/mod.rs | 106 +-- .../infer/region_inference/graphviz.rs | 5 +- src/librustc/middle/cstore.rs | 118 ++-- src/librustc/middle/dataflow.rs | 4 +- src/librustc/middle/dependency_format.rs | 30 +- src/librustc/middle/stability.rs | 5 +- src/librustc/session/mod.rs | 16 +- src/librustc/traits/coherence.rs | 3 +- src/librustc/traits/mod.rs | 2 +- src/librustc/ty/adjustment.rs | 6 +- src/librustc/ty/context.rs | 9 +- src/librustc/ty/item_path.rs | 5 +- src/librustc/ty/layout.rs | 15 +- src/librustc/ty/mod.rs | 13 +- src/librustc/ty/util.rs | 2 +- src/librustc_back/lib.rs | 1 - src/librustc_const_eval/check_match.rs | 4 +- src/librustc_driver/pretty.rs | 1 + src/librustc_driver/test.rs | 19 +- src/librustc_incremental/persist/directory.rs | 16 +- src/librustc_incremental/persist/fs.rs | 7 +- src/librustc_incremental/persist/hash.rs | 9 +- src/librustc_lint/types.rs | 2 +- src/librustc_metadata/astencode.rs | 642 ++---------------- src/librustc_metadata/creader.rs | 30 +- src/librustc_metadata/csearch.rs | 58 +- src/librustc_metadata/cstore.rs | 38 +- src/librustc_metadata/decoder.rs | 246 ++++--- src/librustc_metadata/encoder.rs | 9 +- src/librustc_metadata/tydecode.rs | 24 +- src/librustc_mir/transform/type_check.rs | 3 +- src/librustc_resolve/lib.rs | 4 +- src/librustc_resolve/macros.rs | 2 +- src/librustc_save_analysis/data.rs | 4 +- src/librustc_save_analysis/dump_visitor.rs | 18 +- src/librustc_save_analysis/external_data.rs | 9 +- src/librustc_save_analysis/json_api_dumper.rs | 2 +- src/librustc_save_analysis/json_dumper.rs | 2 +- src/librustc_save_analysis/lib.rs | 6 +- src/librustc_trans/adt.rs | 4 +- src/librustc_trans/back/link.rs | 9 +- src/librustc_trans/back/linker.rs | 4 +- .../back}/rpath.rs | 5 +- src/librustc_trans/back/symbol_names.rs | 8 +- src/librustc_trans/lib.rs | 2 +- src/librustc_trans/type_of.rs | 2 +- src/librustc_typeck/check/callee.rs | 3 +- src/librustc_typeck/check/compare_method.rs | 4 +- src/librustc_typeck/check/mod.rs | 9 +- src/librustc_typeck/coherence/orphan.rs | 3 +- src/librustdoc/clean/mod.rs | 12 +- src/librustdoc/core.rs | 6 +- src/librustdoc/doctree.rs | 5 +- src/librustdoc/html/format.rs | 3 +- src/librustdoc/html/render.rs | 9 +- src/librustdoc/visit_ast.rs | 3 +- src/librustdoc/visit_lib.rs | 5 +- src/libserialize/lib.rs | 3 +- src/libserialize/serialize.rs | 44 -- src/libsyntax/ast.rs | 38 +- src/libsyntax/attr.rs | 6 +- src/libsyntax/ext/expand.rs | 6 +- src/libsyntax/lib.rs | 1 + src/libsyntax_ext/deriving/generic/mod.rs | 22 +- src/libsyntax_pos/lib.rs | 17 +- 70 files changed, 606 insertions(+), 1213 deletions(-) rename src/{librustc_back => librustc_trans/back}/rpath.rs (98%) diff --git a/src/librustc/hir/def_id.rs b/src/librustc/hir/def_id.rs index 16afa705e3919..f36fcfd518733 100644 --- a/src/librustc/hir/def_id.rs +++ b/src/librustc/hir/def_id.rs @@ -8,12 +8,59 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use middle::cstore::LOCAL_CRATE; use ty; -use syntax::ast::CrateNum; + +use rustc_data_structures::indexed_vec::Idx; +use serialize; + use std::fmt; use std::u32; +#[derive(Clone, Copy, Eq, Ord, PartialOrd, PartialEq, RustcEncodable, Hash, Debug)] +pub struct CrateNum(u32); + +impl Idx for CrateNum { + fn new(value: usize) -> Self { + assert!(value < (u32::MAX) as usize); + CrateNum(value as u32) + } + + fn index(self) -> usize { + self.0 as usize + } +} + +/// Item definitions in the currently-compiled crate would have the CrateNum +/// LOCAL_CRATE in their DefId. +pub const LOCAL_CRATE: CrateNum = CrateNum(0); + +impl CrateNum { + pub fn new(x: usize) -> CrateNum { + assert!(x < (u32::MAX as usize)); + CrateNum(x as u32) + } + + pub fn from_u32(x: u32) -> CrateNum { + CrateNum(x) + } + + pub fn as_usize(&self) -> usize { + self.0 as usize + } + + pub fn as_u32(&self) -> u32 { + self.0 + } +} + +impl fmt::Display for CrateNum { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(&self.0, f) + } +} + +impl serialize::UseSpecializedDecodable for CrateNum {} + /// A DefIndex is an index into the hir-map for a crate, identifying a /// particular definition. It should really be considered an interned /// shorthand for a particular DefPath. @@ -46,8 +93,7 @@ pub const CRATE_DEF_INDEX: DefIndex = DefIndex(0); /// A DefId identifies a particular *definition*, by combining a crate /// index and a def index. -#[derive(Clone, Eq, Ord, PartialOrd, PartialEq, RustcEncodable, - RustcDecodable, Hash, Copy)] +#[derive(Clone, Eq, Ord, PartialOrd, PartialEq, RustcEncodable, RustcDecodable, Hash, Copy)] pub struct DefId { pub krate: CrateNum, pub index: DefIndex, diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index f0caa971d9699..726e4e53e231c 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -881,8 +881,8 @@ pub struct IdRange { impl IdRange { pub fn max() -> IdRange { IdRange { - min: u32::MAX, - max: u32::MIN, + min: NodeId::from_u32(u32::MAX), + max: NodeId::from_u32(u32::MIN), } } @@ -896,7 +896,7 @@ impl IdRange { pub fn add(&mut self, id: NodeId) { self.min = cmp::min(self.min, id); - self.max = cmp::max(self.max, id + 1); + self.max = cmp::max(self.max, NodeId::from_u32(id.as_u32() + 1)); } } diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index f7c3eebdc2981..9f7400c983e5a 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -61,7 +61,7 @@ use syntax_pos::Span; pub struct LoweringContext<'a> { crate_root: Option<&'static str>, // Use to assign ids to hir nodes that do not directly correspond to an ast node - sess: Option<&'a Session>, + sess: &'a Session, // As we walk the AST we must keep track of the current 'parent' def id (in // the form of a DefIndex) so that if we create a new node which introduces // a definition, then we can properly create the def id. @@ -101,22 +101,13 @@ pub fn lower_crate(sess: &Session, } else { Some("std") }, - sess: Some(sess), + sess: sess, parent_def: None, resolver: resolver, }.lower_crate(krate) } impl<'a> LoweringContext<'a> { - pub fn testing_context(resolver: &'a mut Resolver) -> Self { - LoweringContext { - crate_root: None, - sess: None, - parent_def: None, - resolver: resolver, - } - } - fn lower_crate(&mut self, c: &Crate) -> hir::Crate { struct ItemLowerer<'lcx, 'interner: 'lcx> { items: BTreeMap, @@ -147,12 +138,11 @@ impl<'a> LoweringContext<'a> { } fn next_id(&self) -> NodeId { - self.sess.map(Session::next_node_id).unwrap_or(0) + self.sess.next_node_id() } fn diagnostic(&self) -> &errors::Handler { - self.sess.map(Session::diagnostic) - .unwrap_or_else(|| panic!("this lowerer cannot emit diagnostics")) + self.sess.diagnostic() } fn str_to_ident(&self, s: &'static str) -> Name { diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index d4e1eb70ae8f9..6c6de8e890245 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -63,10 +63,10 @@ impl<'ast> NodeCollector<'ast> { fn insert_entry(&mut self, id: NodeId, entry: MapEntry<'ast>) { debug!("ast_map: {:?} => {:?}", id, entry); let len = self.map.len(); - if id as usize >= len { - self.map.extend(repeat(NotPresent).take(id as usize - len + 1)); + if id.as_usize() >= len { + self.map.extend(repeat(NotPresent).take(id.as_usize() - len + 1)); } - self.map[id as usize] = entry; + self.map[id.as_usize()] = entry; } fn insert(&mut self, id: NodeId, node: Node<'ast>) { diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index 901a489728eec..c0c28939ab27f 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -8,8 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use middle::cstore::LOCAL_CRATE; -use hir::def_id::{DefId, DefIndex}; +use hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE}; use hir::map::def_collector::DefCollector; use rustc_data_structures::fnv::FnvHashMap; use std::fmt::Write; @@ -70,7 +69,7 @@ pub struct DefPath { pub data: Vec, /// what krate root is this path relative to? - pub krate: ast::CrateNum, + pub krate: CrateNum, } impl DefPath { @@ -78,7 +77,7 @@ impl DefPath { self.krate == LOCAL_CRATE } - pub fn make(start_krate: ast::CrateNum, + pub fn make(start_krate: CrateNum, start_index: DefIndex, mut get_key: FN) -> DefPath where FN: FnMut(DefIndex) -> DefKey diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 5c302d927a718..b728f1cbca097 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -22,17 +22,15 @@ use middle::cstore::InlinedItem as II; use hir::def_id::{CRATE_DEF_INDEX, DefId, DefIndex}; use syntax::abi::Abi; -use syntax::ast::{self, Name, NodeId, DUMMY_NODE_ID, }; +use syntax::ast::{self, Name, NodeId, CRATE_NODE_ID}; use syntax::codemap::Spanned; use syntax_pos::Span; use hir::*; -use hir::fold::Folder; use hir::print as pprust; use arena::TypedArena; use std::cell::RefCell; -use std::cmp; use std::io; use std::mem; @@ -240,7 +238,7 @@ impl<'ast> Map<'ast> { let mut id = id0; if !self.is_inlined_node_id(id) { loop { - match map[id as usize] { + match map[id.as_usize()] { EntryItem(_, item) => { let def_id = self.local_def_id(item.id); // NB ^~~~~~~ @@ -295,7 +293,7 @@ impl<'ast> Map<'ast> { // reading from an inlined def-id is really a read out of // the metadata from which we loaded the item. loop { - match map[id as usize] { + match map[id.as_usize()] { EntryItem(p, _) | EntryForeignItem(p, _) | EntryTraitItem(p, _) | @@ -373,7 +371,7 @@ impl<'ast> Map<'ast> { } fn find_entry(&self, id: NodeId) -> Option> { - self.map.borrow().get(id as usize).cloned() + self.map.borrow().get(id.as_usize()).cloned() } pub fn krate(&self) -> &'ast Crate { @@ -456,8 +454,8 @@ impl<'ast> Map<'ast> { let mut id = start_id; loop { let parent_node = self.get_parent_node(id); - if parent_node == 0 { - return Ok(0); + if parent_node == CRATE_NODE_ID { + return Ok(CRATE_NODE_ID); } if parent_node == id { return Err(id); @@ -680,7 +678,7 @@ impl<'ast> Map<'ast> { map: self, item_name: parts.last().unwrap(), in_which: &parts[..parts.len() - 1], - idx: 0, + idx: CRATE_NODE_ID, } } @@ -801,10 +799,10 @@ impl<'a, 'ast> Iterator for NodesMatchingSuffix<'a, 'ast> { fn next(&mut self) -> Option { loop { let idx = self.idx; - if idx as usize >= self.map.entry_count() { + if idx.as_usize() >= self.map.entry_count() { return None; } - self.idx += 1; + self.idx = NodeId::from_u32(self.idx.as_u32() + 1); let name = match self.map.find_entry(idx) { Some(EntryItem(_, n)) => n.name(), Some(EntryForeignItem(_, n))=> n.name(), @@ -832,57 +830,6 @@ impl Named for Variant_ { fn name(&self) -> Name { self.name } } impl Named for TraitItem { fn name(&self) -> Name { self.name } } impl Named for ImplItem { fn name(&self) -> Name { self.name } } -pub trait FoldOps { - fn new_id(&self, id: NodeId) -> NodeId { - id - } - fn new_def_id(&self, def_id: DefId) -> DefId { - def_id - } - fn new_span(&self, span: Span) -> Span { - span - } -} - -/// A Folder that updates IDs and Span's according to fold_ops. -pub struct IdAndSpanUpdater { - fold_ops: F, - min_id_assigned: NodeId, - max_id_assigned: NodeId, -} - -impl IdAndSpanUpdater { - pub fn new(fold_ops: F) -> IdAndSpanUpdater { - IdAndSpanUpdater { - fold_ops: fold_ops, - min_id_assigned: ::std::u32::MAX, - max_id_assigned: ::std::u32::MIN, - } - } - - pub fn id_range(&self) -> intravisit::IdRange { - intravisit::IdRange { - min: self.min_id_assigned, - max: self.max_id_assigned + 1, - } - } -} - -impl Folder for IdAndSpanUpdater { - fn new_id(&mut self, id: NodeId) -> NodeId { - let id = self.fold_ops.new_id(id); - - self.min_id_assigned = cmp::min(self.min_id_assigned, id); - self.max_id_assigned = cmp::max(self.max_id_assigned, id); - - id - } - - fn new_span(&mut self, span: Span) -> Span { - self.fold_ops.new_span(span) - } -} - pub fn map_crate<'ast>(forest: &'ast mut Forest, definitions: Definitions) -> Map<'ast> { @@ -906,7 +853,7 @@ pub fn map_crate<'ast>(forest: &'ast mut Forest, entries, vector_length, (entries as f64 / vector_length as f64) * 100.); } - let local_node_id_watermark = map.len() as NodeId; + let local_node_id_watermark = NodeId::new(map.len()); let local_def_id_watermark = definitions.len(); Map { @@ -921,36 +868,15 @@ pub fn map_crate<'ast>(forest: &'ast mut Forest, /// Used for items loaded from external crate that are being inlined into this /// crate. -pub fn map_decoded_item<'ast, F: FoldOps>(map: &Map<'ast>, - parent_def_path: DefPath, - parent_def_id: DefId, - ii: InlinedItem, - fold_ops: F) - -> &'ast InlinedItem { +pub fn map_decoded_item<'ast>(map: &Map<'ast>, + parent_def_path: DefPath, + parent_def_id: DefId, + ii: InlinedItem, + ii_parent_id: NodeId) + -> &'ast InlinedItem { let _ignore = map.forest.dep_graph.in_ignore(); - let mut fld = IdAndSpanUpdater::new(fold_ops); - let ii = match ii { - II::Item(d, i) => II::Item(fld.fold_ops.new_def_id(d), - i.map(|i| fld.fold_item(i))), - II::TraitItem(d, ti) => { - II::TraitItem(fld.fold_ops.new_def_id(d), - ti.map(|ti| fld.fold_trait_item(ti))) - } - II::ImplItem(d, ii) => { - II::ImplItem(fld.fold_ops.new_def_id(d), - ii.map(|ii| fld.fold_impl_item(ii))) - } - }; - let ii = map.forest.inlined_items.alloc(ii); - let ii_parent_id = fld.new_id(DUMMY_NODE_ID); - - // Assert that the ii_parent_id is the last NodeId in our reserved range - assert!(ii_parent_id == fld.max_id_assigned); - // Assert that we did not violate the invariant that all inlined HIR items - // have NodeIds greater than or equal to `local_node_id_watermark` - assert!(fld.min_id_assigned >= map.local_node_id_watermark); let defs = &mut *map.definitions.borrow_mut(); let mut def_collector = DefCollector::extend(ii_parent_id, diff --git a/src/librustc/infer/region_inference/graphviz.rs b/src/librustc/infer/region_inference/graphviz.rs index 1c64ebc0537ae..289f7d6c73800 100644 --- a/src/librustc/infer/region_inference/graphviz.rs +++ b/src/librustc/infer/region_inference/graphviz.rs @@ -63,9 +63,8 @@ pub fn maybe_print_constraints_for<'a, 'gcx, 'tcx>( return; } - let requested_node: Option = env::var("RUST_REGION_GRAPH_NODE") - .ok() - .and_then(|s| s.parse().ok()); + let requested_node = env::var("RUST_REGION_GRAPH_NODE") + .ok().and_then(|s| s.parse().map(ast::NodeId::new).ok()); if requested_node.is_some() && requested_node != Some(subject_node) { return; diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index c201c47ef5c40..55a895b37ee33 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -23,7 +23,7 @@ // probably get a better home if someone can find one. use hir::def::{self, Def}; -use hir::def_id::{DefId, DefIndex}; +use hir::def_id::{CrateNum, DefId, DefIndex}; use hir::map as hir_map; use hir::map::definitions::DefKey; use hir::svh::Svh; @@ -64,7 +64,7 @@ pub struct LinkMeta { pub struct CrateSource { pub dylib: Option<(PathBuf, PathKind)>, pub rlib: Option<(PathBuf, PathKind)>, - pub cnum: ast::CrateNum, + pub cnum: CrateNum, } #[derive(Copy, Debug, PartialEq, Clone)] @@ -101,17 +101,13 @@ pub enum InlinedItem { } /// A borrowed version of `hir::InlinedItem`. -#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, Hash, Debug)] pub enum InlinedItemRef<'a> { Item(DefId, &'a hir::Item), TraitItem(DefId, &'a hir::TraitItem), ImplItem(DefId, &'a hir::ImplItem) } -/// Item definitions in the currently-compiled crate would have the CrateNum -/// LOCAL_CRATE in their DefId. -pub const LOCAL_CRATE: ast::CrateNum = 0; - #[derive(Copy, Clone)] pub struct ChildItem { pub def: DefLike, @@ -203,35 +199,35 @@ pub trait CrateStore<'tcx> { fn is_typedef(&self, did: DefId) -> bool; // crate metadata - fn dylib_dependency_formats(&self, cnum: ast::CrateNum) - -> Vec<(ast::CrateNum, LinkagePreference)>; - fn lang_items(&self, cnum: ast::CrateNum) -> Vec<(DefIndex, usize)>; - fn missing_lang_items(&self, cnum: ast::CrateNum) -> Vec; - fn is_staged_api(&self, cnum: ast::CrateNum) -> bool; - fn is_explicitly_linked(&self, cnum: ast::CrateNum) -> bool; - fn is_allocator(&self, cnum: ast::CrateNum) -> bool; - fn is_panic_runtime(&self, cnum: ast::CrateNum) -> bool; - fn is_compiler_builtins(&self, cnum: ast::CrateNum) -> bool; - fn panic_strategy(&self, cnum: ast::CrateNum) -> PanicStrategy; - fn extern_crate(&self, cnum: ast::CrateNum) -> Option; - fn crate_attrs(&self, cnum: ast::CrateNum) -> Vec; + fn dylib_dependency_formats(&self, cnum: CrateNum) + -> Vec<(CrateNum, LinkagePreference)>; + fn lang_items(&self, cnum: CrateNum) -> Vec<(DefIndex, usize)>; + fn missing_lang_items(&self, cnum: CrateNum) -> Vec; + fn is_staged_api(&self, cnum: CrateNum) -> bool; + fn is_explicitly_linked(&self, cnum: CrateNum) -> bool; + fn is_allocator(&self, cnum: CrateNum) -> bool; + fn is_panic_runtime(&self, cnum: CrateNum) -> bool; + fn is_compiler_builtins(&self, cnum: CrateNum) -> bool; + fn panic_strategy(&self, cnum: CrateNum) -> PanicStrategy; + fn extern_crate(&self, cnum: CrateNum) -> Option; + fn crate_attrs(&self, cnum: CrateNum) -> Vec; /// The name of the crate as it is referred to in source code of the current /// crate. - fn crate_name(&self, cnum: ast::CrateNum) -> InternedString; + fn crate_name(&self, cnum: CrateNum) -> InternedString; /// The name of the crate as it is stored in the crate's metadata. - fn original_crate_name(&self, cnum: ast::CrateNum) -> InternedString; - fn crate_hash(&self, cnum: ast::CrateNum) -> Svh; - fn crate_disambiguator(&self, cnum: ast::CrateNum) -> InternedString; - fn crate_struct_field_attrs(&self, cnum: ast::CrateNum) + fn original_crate_name(&self, cnum: CrateNum) -> InternedString; + fn crate_hash(&self, cnum: CrateNum) -> Svh; + fn crate_disambiguator(&self, cnum: CrateNum) -> InternedString; + fn crate_struct_field_attrs(&self, cnum: CrateNum) -> FnvHashMap>; - fn plugin_registrar_fn(&self, cnum: ast::CrateNum) -> Option; - fn native_libraries(&self, cnum: ast::CrateNum) -> Vec<(NativeLibraryKind, String)>; - fn reachable_ids(&self, cnum: ast::CrateNum) -> Vec; - fn is_no_builtins(&self, cnum: ast::CrateNum) -> bool; + fn plugin_registrar_fn(&self, cnum: CrateNum) -> Option; + fn native_libraries(&self, cnum: CrateNum) -> Vec<(NativeLibraryKind, String)>; + fn reachable_ids(&self, cnum: CrateNum) -> Vec; + fn is_no_builtins(&self, cnum: CrateNum) -> bool; // resolve fn def_index_for_def_key(&self, - cnum: ast::CrateNum, + cnum: CrateNum, def: DefKey) -> Option; fn def_key(&self, def: DefId) -> hir_map::DefKey; @@ -241,7 +237,7 @@ pub trait CrateStore<'tcx> { fn tuple_struct_definition_if_ctor(&self, did: DefId) -> Option; fn struct_field_names(&self, def: DefId) -> Vec; fn item_children(&self, did: DefId) -> Vec; - fn crate_top_level_items(&self, cnum: ast::CrateNum) -> Vec; + fn crate_top_level_items(&self, cnum: CrateNum) -> Vec; // misc. metadata fn maybe_get_item_ast<'a>(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) @@ -255,7 +251,7 @@ pub trait CrateStore<'tcx> { // This is basically a 1-based range of ints, which is a little // silly - I may fix that. - fn crates(&self) -> Vec; + fn crates(&self) -> Vec; fn used_libraries(&self) -> Vec<(String, NativeLibraryKind)>; fn used_link_args(&self) -> Vec; @@ -267,9 +263,9 @@ pub trait CrateStore<'tcx> { ty: Ty<'tcx>, def_id_to_string: for<'b> fn(TyCtxt<'b, 'tcx, 'tcx>, DefId) -> String) -> Vec; - fn used_crates(&self, prefer: LinkagePreference) -> Vec<(ast::CrateNum, Option)>; - fn used_crate_source(&self, cnum: ast::CrateNum) -> CrateSource; - fn extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option; + fn used_crates(&self, prefer: LinkagePreference) -> Vec<(CrateNum, Option)>; + fn used_crate_source(&self, cnum: CrateNum) -> CrateSource; + fn extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option; fn encode_metadata<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, reexports: &def::ExportMap, link_meta: &LinkMeta, @@ -360,7 +356,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { fn trait_item_def_ids(&self, def: DefId) -> Vec { bug!("trait_item_def_ids") } fn def_index_for_def_key(&self, - cnum: ast::CrateNum, + cnum: CrateNum, def: DefKey) -> Option { None @@ -396,40 +392,40 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { fn is_typedef(&self, did: DefId) -> bool { bug!("is_typedef") } // crate metadata - fn dylib_dependency_formats(&self, cnum: ast::CrateNum) - -> Vec<(ast::CrateNum, LinkagePreference)> + fn dylib_dependency_formats(&self, cnum: CrateNum) + -> Vec<(CrateNum, LinkagePreference)> { bug!("dylib_dependency_formats") } - fn lang_items(&self, cnum: ast::CrateNum) -> Vec<(DefIndex, usize)> + fn lang_items(&self, cnum: CrateNum) -> Vec<(DefIndex, usize)> { bug!("lang_items") } - fn missing_lang_items(&self, cnum: ast::CrateNum) -> Vec + fn missing_lang_items(&self, cnum: CrateNum) -> Vec { bug!("missing_lang_items") } - fn is_staged_api(&self, cnum: ast::CrateNum) -> bool { bug!("is_staged_api") } - fn is_explicitly_linked(&self, cnum: ast::CrateNum) -> bool { bug!("is_explicitly_linked") } - fn is_allocator(&self, cnum: ast::CrateNum) -> bool { bug!("is_allocator") } - fn is_panic_runtime(&self, cnum: ast::CrateNum) -> bool { bug!("is_panic_runtime") } - fn is_compiler_builtins(&self, cnum: ast::CrateNum) -> bool { bug!("is_compiler_builtins") } - fn panic_strategy(&self, cnum: ast::CrateNum) -> PanicStrategy { + fn is_staged_api(&self, cnum: CrateNum) -> bool { bug!("is_staged_api") } + fn is_explicitly_linked(&self, cnum: CrateNum) -> bool { bug!("is_explicitly_linked") } + fn is_allocator(&self, cnum: CrateNum) -> bool { bug!("is_allocator") } + fn is_panic_runtime(&self, cnum: CrateNum) -> bool { bug!("is_panic_runtime") } + fn is_compiler_builtins(&self, cnum: CrateNum) -> bool { bug!("is_compiler_builtins") } + fn panic_strategy(&self, cnum: CrateNum) -> PanicStrategy { bug!("panic_strategy") } - fn extern_crate(&self, cnum: ast::CrateNum) -> Option { bug!("extern_crate") } - fn crate_attrs(&self, cnum: ast::CrateNum) -> Vec + fn extern_crate(&self, cnum: CrateNum) -> Option { bug!("extern_crate") } + fn crate_attrs(&self, cnum: CrateNum) -> Vec { bug!("crate_attrs") } - fn crate_name(&self, cnum: ast::CrateNum) -> InternedString { bug!("crate_name") } - fn original_crate_name(&self, cnum: ast::CrateNum) -> InternedString { + fn crate_name(&self, cnum: CrateNum) -> InternedString { bug!("crate_name") } + fn original_crate_name(&self, cnum: CrateNum) -> InternedString { bug!("original_crate_name") } - fn crate_hash(&self, cnum: ast::CrateNum) -> Svh { bug!("crate_hash") } - fn crate_disambiguator(&self, cnum: ast::CrateNum) + fn crate_hash(&self, cnum: CrateNum) -> Svh { bug!("crate_hash") } + fn crate_disambiguator(&self, cnum: CrateNum) -> InternedString { bug!("crate_disambiguator") } - fn crate_struct_field_attrs(&self, cnum: ast::CrateNum) + fn crate_struct_field_attrs(&self, cnum: CrateNum) -> FnvHashMap> { bug!("crate_struct_field_attrs") } - fn plugin_registrar_fn(&self, cnum: ast::CrateNum) -> Option + fn plugin_registrar_fn(&self, cnum: CrateNum) -> Option { bug!("plugin_registrar_fn") } - fn native_libraries(&self, cnum: ast::CrateNum) -> Vec<(NativeLibraryKind, String)> + fn native_libraries(&self, cnum: CrateNum) -> Vec<(NativeLibraryKind, String)> { bug!("native_libraries") } - fn reachable_ids(&self, cnum: ast::CrateNum) -> Vec { bug!("reachable_ids") } - fn is_no_builtins(&self, cnum: ast::CrateNum) -> bool { bug!("is_no_builtins") } + fn reachable_ids(&self, cnum: CrateNum) -> Vec { bug!("reachable_ids") } + fn is_no_builtins(&self, cnum: CrateNum) -> bool { bug!("is_no_builtins") } // resolve fn def_key(&self, def: DefId) -> hir_map::DefKey { bug!("def_key") } @@ -443,7 +439,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { { bug!("tuple_struct_definition_if_ctor") } fn struct_field_names(&self, def: DefId) -> Vec { bug!("struct_field_names") } fn item_children(&self, did: DefId) -> Vec { bug!("item_children") } - fn crate_top_level_items(&self, cnum: ast::CrateNum) -> Vec + fn crate_top_level_items(&self, cnum: CrateNum) -> Vec { bug!("crate_top_level_items") } // misc. metadata @@ -466,7 +462,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { // This is basically a 1-based range of ints, which is a little // silly - I may fix that. - fn crates(&self) -> Vec { vec![] } + fn crates(&self) -> Vec { vec![] } fn used_libraries(&self) -> Vec<(String, NativeLibraryKind)> { vec![] } fn used_link_args(&self) -> Vec { vec![] } @@ -480,10 +476,10 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { -> Vec { bug!("encode_type") } - fn used_crates(&self, prefer: LinkagePreference) -> Vec<(ast::CrateNum, Option)> + fn used_crates(&self, prefer: LinkagePreference) -> Vec<(CrateNum, Option)> { vec![] } - fn used_crate_source(&self, cnum: ast::CrateNum) -> CrateSource { bug!("used_crate_source") } - fn extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option { None } + fn used_crate_source(&self, cnum: CrateNum) -> CrateSource { bug!("used_crate_source") } + fn extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option { None } fn encode_metadata<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, reexports: &def::ExportMap, link_meta: &LinkMeta, diff --git a/src/librustc/middle/dataflow.rs b/src/librustc/middle/dataflow.rs index fc1294c86c44f..7f3a58808c225 100644 --- a/src/librustc/middle/dataflow.rs +++ b/src/librustc/middle/dataflow.rs @@ -112,10 +112,10 @@ impl<'a, 'tcx, O:DataFlowOperator> pprust::PpAnn for DataFlowContext<'a, 'tcx, O ps: &mut pprust::State, node: pprust::AnnNode) -> io::Result<()> { let id = match node { - pprust::NodeName(_) => 0, + pprust::NodeName(_) => ast::CRATE_NODE_ID, pprust::NodeExpr(expr) => expr.id, pprust::NodeBlock(blk) => blk.id, - pprust::NodeItem(_) | pprust::NodeSubItem(_) => 0, + pprust::NodeItem(_) | pprust::NodeSubItem(_) => ast::CRATE_NODE_ID, pprust::NodePat(pat) => pat.id }; diff --git a/src/librustc/middle/dependency_format.rs b/src/librustc/middle/dependency_format.rs index 7822fe2536f1f..c6908e11ed209 100644 --- a/src/librustc/middle/dependency_format.rs +++ b/src/librustc/middle/dependency_format.rs @@ -61,7 +61,7 @@ //! Additionally, the algorithm is geared towards finding *any* solution rather //! than finding a number of solutions (there are normally quite a few). -use syntax::ast; +use hir::def_id::CrateNum; use session; use session::config::{self, PanicStrategy}; @@ -169,9 +169,9 @@ fn calculate_type(sess: &session::Session, } // Collect what we've got so far in the return vector. - let last_crate = sess.cstore.crates().len() as ast::CrateNum; + let last_crate = sess.cstore.crates().len(); let mut ret = (1..last_crate+1).map(|cnum| { - match formats.get(&cnum) { + match formats.get(&CrateNum::new(cnum)) { Some(&RequireDynamic) => Linkage::Dynamic, Some(&RequireStatic) => Linkage::IncludedFromDylib, None => Linkage::NotLinked, @@ -191,7 +191,7 @@ fn calculate_type(sess: &session::Session, assert!(src.rlib.is_some()); info!("adding staticlib: {}", sess.cstore.crate_name(cnum)); add_library(sess, cnum, RequireStatic, &mut formats); - ret[cnum as usize - 1] = Linkage::Static; + ret[cnum.as_usize() - 1] = Linkage::Static; } } @@ -213,7 +213,7 @@ fn calculate_type(sess: &session::Session, // For situations like this, we perform one last pass over the dependencies, // making sure that everything is available in the requested format. for (cnum, kind) in ret.iter().enumerate() { - let cnum = (cnum + 1) as ast::CrateNum; + let cnum = CrateNum::new(cnum + 1); let src = sess.cstore.used_crate_source(cnum); match *kind { Linkage::NotLinked | @@ -237,9 +237,9 @@ fn calculate_type(sess: &session::Session, } fn add_library(sess: &session::Session, - cnum: ast::CrateNum, + cnum: CrateNum, link: LinkagePreference, - m: &mut FnvHashMap) { + m: &mut FnvHashMap) { match m.get(&cnum) { Some(&link2) => { // If the linkages differ, then we'd have two copies of the library @@ -269,9 +269,9 @@ fn attempt_static(sess: &session::Session) -> Option { // All crates are available in an rlib format, so we're just going to link // everything in explicitly so long as it's actually required. - let last_crate = sess.cstore.crates().len() as ast::CrateNum; + let last_crate = sess.cstore.crates().len(); let mut ret = (1..last_crate+1).map(|cnum| { - if sess.cstore.is_explicitly_linked(cnum) { + if sess.cstore.is_explicitly_linked(CrateNum::new(cnum)) { Linkage::Static } else { Linkage::NotLinked @@ -298,11 +298,11 @@ fn attempt_static(sess: &session::Session) -> Option { // a required dependency) in one of the session's field. If this field is not // set then this compilation doesn't actually need the dependency and we can // also skip this step entirely. -fn activate_injected_dep(injected: Option, +fn activate_injected_dep(injected: Option, list: &mut DependencyList, - replaces_injected: &Fn(ast::CrateNum) -> bool) { + replaces_injected: &Fn(CrateNum) -> bool) { for (i, slot) in list.iter().enumerate() { - let cnum = (i + 1) as ast::CrateNum; + let cnum = CrateNum::new(i + 1); if !replaces_injected(cnum) { continue } @@ -311,7 +311,7 @@ fn activate_injected_dep(injected: Option, } } if let Some(injected) = injected { - let idx = injected as usize - 1; + let idx = injected.as_usize() - 1; assert_eq!(list[idx], Linkage::NotLinked); list[idx] = Linkage::Static; } @@ -329,7 +329,7 @@ fn verify_ok(sess: &session::Session, list: &[Linkage]) { if let Linkage::NotLinked = *linkage { continue } - let cnum = (i + 1) as ast::CrateNum; + let cnum = CrateNum::new(i + 1); if sess.cstore.is_allocator(cnum) { if let Some(prev) = allocator { let prev_name = sess.cstore.crate_name(prev); @@ -380,7 +380,7 @@ fn verify_ok(sess: &session::Session, list: &[Linkage]) { if desired_strategy == PanicStrategy::Abort { continue } - let cnum = (i + 1) as ast::CrateNum; + let cnum = CrateNum::new(i + 1); let found_strategy = sess.cstore.panic_strategy(cnum); if desired_strategy == found_strategy { continue diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 9a56959de38bc..e2b997ed60f2d 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -17,9 +17,8 @@ use dep_graph::DepNode; use hir::map as hir_map; use session::Session; use lint; -use middle::cstore::LOCAL_CRATE; use hir::def::Def; -use hir::def_id::{CRATE_DEF_INDEX, DefId, DefIndex}; +use hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, DefIndex, LOCAL_CRATE}; use ty::{self, TyCtxt, AdtKind}; use middle::privacy::AccessLevels; use syntax::parse::token::InternedString; @@ -103,7 +102,7 @@ pub struct Index<'tcx> { depr_map: DefIdMap>, /// Maps for each crate whether it is part of the staged API. - staged_api: FnvHashMap + staged_api: FnvHashMap } // A private tree-walker for producing an Index. diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 49686d63ee43b..268dbd70bb5bb 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -9,7 +9,7 @@ // except according to those terms. use dep_graph::DepGraph; -use hir::def_id::DefIndex; +use hir::def_id::{CrateNum, DefIndex}; use hir::svh::Svh; use lint; use middle::cstore::CrateStore; @@ -93,8 +93,8 @@ pub struct Session { /// The metadata::creader module may inject an allocator/panic_runtime /// dependency if it didn't already find one, and this tracks what was /// injected. - pub injected_allocator: Cell>, - pub injected_panic_runtime: Cell>, + pub injected_allocator: Cell>, + pub injected_panic_runtime: Cell>, /// Map from imported macro spans (which consist of /// the localized span for the macro body) to the @@ -266,11 +266,13 @@ impl Session { } lints.insert(id, vec!((lint_id, sp, msg))); } - pub fn reserve_node_ids(&self, count: ast::NodeId) -> ast::NodeId { + pub fn reserve_node_ids(&self, count: usize) -> ast::NodeId { let id = self.next_node_id.get(); - match id.checked_add(count) { - Some(next) => self.next_node_id.set(next), + match id.as_usize().checked_add(count) { + Some(next) => { + self.next_node_id.set(ast::NodeId::new(next)); + } None => bug!("Input too large, ran out of node ids!") } @@ -545,7 +547,7 @@ pub fn build_session_(sopts: config::Options, crate_disambiguator: RefCell::new(token::intern("").as_str()), features: RefCell::new(feature_gate::Features::new()), recursion_limit: Cell::new(64), - next_node_id: Cell::new(1), + next_node_id: Cell::new(NodeId::new(1)), injected_allocator: Cell::new(None), injected_panic_runtime: Cell::new(None), imported_macro_spans: RefCell::new(HashMap::new()), diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs index 83774f0cf7ead..68c88249ec0c3 100644 --- a/src/librustc/traits/coherence.rs +++ b/src/librustc/traits/coherence.rs @@ -12,8 +12,7 @@ use super::{SelectionContext, Obligation, ObligationCause}; -use middle::cstore::LOCAL_CRATE; -use hir::def_id::DefId; +use hir::def_id::{DefId, LOCAL_CRATE}; use ty::{self, Ty, TyCtxt}; use infer::{InferCtxt, TypeOrigin}; use syntax_pos::DUMMY_SP; diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index b86a54f01cf49..a96cf1111e1d3 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -571,7 +571,7 @@ impl<'tcx> ObligationCause<'tcx> { } pub fn dummy() -> ObligationCause<'tcx> { - ObligationCause { span: DUMMY_SP, body_id: 0, code: MiscObligation } + ObligationCause { span: DUMMY_SP, body_id: ast::CRATE_NODE_ID, code: MiscObligation } } } diff --git a/src/librustc/ty/adjustment.rs b/src/librustc/ty/adjustment.rs index 3386d894196fa..cfe370343ae49 100644 --- a/src/librustc/ty/adjustment.rs +++ b/src/librustc/ty/adjustment.rs @@ -19,7 +19,7 @@ use syntax_pos::Span; use hir; -#[derive(Copy, Clone)] +#[derive(Copy, Clone, RustcEncodable, RustcDecodable)] pub enum AutoAdjustment<'tcx> { AdjustNeverToAny(Ty<'tcx>), // go from ! to any type AdjustReifyFnPointer, // go from a fn-item type to a fn-pointer type @@ -90,7 +90,7 @@ pub enum AutoAdjustment<'tcx> { /// unsize: Some(Box<[i32]>), /// } /// ``` -#[derive(Copy, Clone)] +#[derive(Copy, Clone, RustcEncodable, RustcDecodable)] pub struct AutoDerefRef<'tcx> { /// Step 1. Apply a number of dereferences, producing an lvalue. pub autoderefs: usize, @@ -122,7 +122,7 @@ impl<'tcx> AutoDerefRef<'tcx> { } -#[derive(Copy, Clone, PartialEq, Debug)] +#[derive(Copy, Clone, PartialEq, Debug, RustcEncodable, RustcDecodable)] pub enum AutoRef<'tcx> { /// Convert from T to &T. AutoPtr(&'tcx ty::Region, hir::Mutability), diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 6d7a2d6cba1c7..bb9e90f891942 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -13,10 +13,9 @@ use dep_graph::{DepGraph, DepTrackingMap}; use session::Session; use middle; -use middle::cstore::LOCAL_CRATE; use hir::TraitMap; use hir::def::DefMap; -use hir::def_id::{DefId, DefIndex}; +use hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE}; use hir::map as ast_map; use hir::map::{DefKey, DefPath, DefPathData, DisambiguatedDefPathData}; use middle::free_region::FreeRegionMap; @@ -512,7 +511,7 @@ impl<'tcx> GlobalCtxt<'tcx> { } impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { - pub fn crate_name(self, cnum: ast::CrateNum) -> token::InternedString { + pub fn crate_name(self, cnum: CrateNum) -> token::InternedString { if cnum == LOCAL_CRATE { self.crate_name.clone() } else { @@ -520,7 +519,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } - pub fn crate_disambiguator(self, cnum: ast::CrateNum) -> token::InternedString { + pub fn crate_disambiguator(self, cnum: CrateNum) -> token::InternedString { if cnum == LOCAL_CRATE { self.sess.local_crate_disambiguator() } else { @@ -533,7 +532,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// relative to `krate`. /// /// Returns `None` if there is no `DefIndex` with that key. - pub fn def_index_for_def_key(self, krate: ast::CrateNum, key: DefKey) + pub fn def_index_for_def_key(self, krate: CrateNum, key: DefKey) -> Option { if krate == LOCAL_CRATE { self.map.def_index_for_def_key(key) diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index b6b55fc0e33dd..e4247a60b15ec 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -9,8 +9,7 @@ // except according to those terms. use hir::map::DefPathData; -use middle::cstore::LOCAL_CRATE; -use hir::def_id::{DefId, CRATE_DEF_INDEX}; +use hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use ty::{self, Ty, TyCtxt}; use syntax::ast; use syntax::parse::token; @@ -67,7 +66,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// Returns the "path" to a particular crate. This can proceed in /// various ways, depending on the `root_mode` of the `buffer`. /// (See `RootMode` enum for more details.) - pub fn push_krate_path(self, buffer: &mut T, cnum: ast::CrateNum) + pub fn push_krate_path(self, buffer: &mut T, cnum: CrateNum) where T: ItemPathBuffer { match *buffer.root_mode() { diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 6fec698cfac9b..5e7a2bc0266cf 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -367,7 +367,7 @@ impl Integer { /// signed discriminant range and #[repr] attribute. /// N.B.: u64 values above i64::MAX will be treated as signed, but /// that shouldn't affect anything, other than maybe debuginfo. - pub fn repr_discr(tcx: TyCtxt, hint: attr::ReprAttr, min: i64, max: i64) + pub fn repr_discr(tcx: TyCtxt, ty: Ty, hint: attr::ReprAttr, min: i64, max: i64) -> (Integer, bool) { // Theoretically, negative values could be larger in unsigned representation // than the unsigned representation of the signed minimum. However, if there @@ -377,11 +377,12 @@ impl Integer { let signed_fit = cmp::max(Integer::fit_signed(min), Integer::fit_signed(max)); let at_least = match hint { - attr::ReprInt(span, ity) => { + attr::ReprInt(ity) => { let discr = Integer::from_attr(&tcx.data_layout, ity); let fit = if ity.is_signed() { signed_fit } else { unsigned_fit }; if discr < fit { - span_bug!(span, "representation hint insufficient for discriminant range") + bug!("Integer::repr_discr: `#[repr]` hint too small for \ + discriminant range of enum `{}", ty) } return (discr, ity.is_signed()); } @@ -397,10 +398,10 @@ impl Integer { } attr::ReprAny => I8, attr::ReprPacked => { - bug!("Integer::repr_discr: found #[repr(packed)] on an enum"); + bug!("Integer::repr_discr: found #[repr(packed)] on enum `{}", ty); } attr::ReprSimd => { - bug!("Integer::repr_discr: found #[repr(simd)] on an enum"); + bug!("Integer::repr_discr: found #[repr(simd)] on enum `{}", ty); } }; @@ -962,7 +963,7 @@ impl<'a, 'gcx, 'tcx> Layout { if x > max { max = x; } } - let (discr, signed) = Integer::repr_discr(tcx, hint, min, max); + let (discr, signed) = Integer::repr_discr(tcx, ty, hint, min, max); return success(CEnum { discr: discr, signed: signed, @@ -1052,7 +1053,7 @@ impl<'a, 'gcx, 'tcx> Layout { // The general case. let discr_max = (variants.len() - 1) as i64; assert!(discr_max >= 0); - let (min_ity, _) = Integer::repr_discr(tcx, hint, 0, discr_max); + let (min_ity, _) = Integer::repr_discr(tcx, ty, hint, 0, discr_max); let mut align = dl.aggregate_align; let mut size = Size::from_bytes(0); diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index c49094cb6881e..6cabc25df6afa 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -21,9 +21,8 @@ pub use self::fold::TypeFoldable; use dep_graph::{self, DepNode}; use hir::map as ast_map; use middle; -use middle::cstore::LOCAL_CRATE; use hir::def::{Def, PathResolution, ExportMap}; -use hir::def_id::DefId; +use hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem}; use middle::region::{CodeExtent, ROOT_CODE_EXTENT}; use traits; @@ -42,7 +41,7 @@ use std::iter; use std::rc::Rc; use std::slice; use std::vec::IntoIter; -use syntax::ast::{self, CrateNum, Name, NodeId}; +use syntax::ast::{self, Name, NodeId}; use syntax::attr; use syntax::parse::token::InternedString; use syntax_pos::{DUMMY_SP, Span}; @@ -425,7 +424,7 @@ pub enum Variance { Bivariant, // T <: T -- e.g., unused type parameter } -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Copy, Debug, RustcDecodable, RustcEncodable)] pub struct MethodCallee<'tcx> { /// Impl method ID, for inherent methods, or trait method ID, otherwise. pub def_id: DefId, @@ -627,7 +626,7 @@ pub enum BorrowKind { /// Information describing the capture of an upvar. This is computed /// during `typeck`, specifically by `regionck`. -#[derive(PartialEq, Clone, Debug, Copy)] +#[derive(PartialEq, Clone, Debug, Copy, RustcEncodable, RustcDecodable)] pub enum UpvarCapture<'tcx> { /// Upvar is captured by value. This is always true when the /// closure is labeled `move`, but can also be true in other cases @@ -638,7 +637,7 @@ pub enum UpvarCapture<'tcx> { ByRef(UpvarBorrow<'tcx>), } -#[derive(PartialEq, Clone, Copy)] +#[derive(PartialEq, Clone, Copy, RustcEncodable, RustcDecodable)] pub struct UpvarBorrow<'tcx> { /// The kind of borrow: by-ref upvars have access to shared /// immutable borrows, which are not part of the normal language @@ -1940,7 +1939,7 @@ impl<'a, 'gcx, 'tcx, 'container> FieldDefData<'tcx, 'container> { /// Records the substitutions used to translate the polytype for an /// item into the monotype of an item reference. -#[derive(Clone)] +#[derive(Clone, RustcEncodable, RustcDecodable)] pub struct ItemSubsts<'tcx> { pub substs: &'tcx Substs<'tcx>, } diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index d34fdaa7d71cd..2090877fb3c92 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -240,7 +240,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn enum_repr_type(self, opt_hint: Option<&attr::ReprAttr>) -> attr::IntType { match opt_hint { // Feed in the given type - Some(&attr::ReprInt(_, int_t)) => int_t, + Some(&attr::ReprInt(int_t)) => int_t, // ... but provide sensible default if none provided // // NB. Historically `fn enum_variants` generate i64 here, while diff --git a/src/librustc_back/lib.rs b/src/librustc_back/lib.rs index 6a7bc51d15a42..f7ae47d2e5e56 100644 --- a/src/librustc_back/lib.rs +++ b/src/librustc_back/lib.rs @@ -46,7 +46,6 @@ extern crate serialize; #[macro_use] extern crate log; pub mod tempdir; -pub mod rpath; pub mod sha2; pub mod target; pub mod slice; diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs index a1e7d0a1e34de..5d2b266ec4b7f 100644 --- a/src/librustc_const_eval/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -460,7 +460,7 @@ fn const_val_to_expr(value: &ConstVal) -> P { _ => bug!() }; P(hir::Expr { - id: 0, + id: DUMMY_NODE_ID, node: hir::ExprLit(P(Spanned { node: node, span: DUMMY_SP })), span: DUMMY_SP, attrs: ast::ThinVec::new(), @@ -625,7 +625,7 @@ fn construct_witness<'a,'tcx>(cx: &MatchCheckCtxt<'a,'tcx>, ctor: &Constructor, }; P(hir::Pat { - id: 0, + id: DUMMY_NODE_ID, node: pat, span: DUMMY_SP }) diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index 1ffeaf322bf57..215287f84399c 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -539,6 +539,7 @@ impl FromStr for UserIdentifiedItem { type Err = (); fn from_str(s: &str) -> Result { Ok(s.parse() + .map(ast::NodeId::new) .map(ItemViaNode) .unwrap_or_else(|_| ItemViaPath(s.split("::").map(|s| s.to_string()).collect()))) } diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index 8569ff64f9100..f6772b8771844 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -166,16 +166,17 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> { pub fn create_simple_region_hierarchy(&self) { // creates a region hierarchy where 1 is root, 10 and 11 are // children of 1, etc + + let node = ast::NodeId::from_u32; let dscope = self.infcx .tcx .region_maps - .intern_code_extent(CodeExtentData::DestructionScope(1), + .intern_code_extent(CodeExtentData::DestructionScope(node(1)), region::ROOT_CODE_EXTENT); self.create_region_hierarchy(&RH { - id: 1, - sub: &[RH { id: 10, sub: &[] }, RH { id: 11, sub: &[] }], - }, - dscope); + id: node(1), + sub: &[RH { id: node(10), sub: &[] }, RH { id: node(11), sub: &[] }], + }, dscope); } #[allow(dead_code)] // this seems like it could be useful, even if we don't use it now @@ -315,8 +316,8 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> { self.infcx.tcx.mk_imm_ref(r, self.tcx().types.isize) } - pub fn t_rptr_scope(&self, id: ast::NodeId) -> Ty<'tcx> { - let r = ty::ReScope(self.tcx().region_maps.node_extent(id)); + pub fn t_rptr_scope(&self, id: u32) -> Ty<'tcx> { + let r = ty::ReScope(self.tcx().region_maps.node_extent(ast::NodeId::from_u32(id))); self.infcx.tcx.mk_imm_ref(self.infcx.tcx.mk_region(r), self.tcx().types.isize) } @@ -327,8 +328,8 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> { })) } - pub fn t_rptr_free(&self, nid: ast::NodeId, id: u32) -> Ty<'tcx> { - let r = self.re_free(nid, id); + pub fn t_rptr_free(&self, nid: u32, id: u32) -> Ty<'tcx> { + let r = self.re_free(ast::NodeId::from_u32(nid), id); self.infcx.tcx.mk_imm_ref(r, self.tcx().types.isize) } diff --git a/src/librustc_incremental/persist/directory.rs b/src/librustc_incremental/persist/directory.rs index 89a79d1a487e0..cca364f442d59 100644 --- a/src/librustc_incremental/persist/directory.rs +++ b/src/librustc_incremental/persist/directory.rs @@ -15,13 +15,11 @@ use rustc::dep_graph::DepNode; use rustc::hir::map::DefPath; -use rustc::hir::def_id::DefId; -use rustc::middle::cstore::LOCAL_CRATE; +use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc::ty::TyCtxt; use rustc::util::nodemap::DefIdMap; use std::fmt::{self, Debug}; use std::iter::once; -use syntax::ast; /// Index into the DefIdDirectory #[derive(Copy, Clone, Debug, PartialOrd, Ord, Hash, PartialEq, Eq, @@ -43,7 +41,7 @@ pub struct DefIdDirectory { #[derive(Debug, RustcEncodable, RustcDecodable)] pub struct CrateInfo { - krate: ast::CrateNum, + krate: CrateNum, name: String, disambiguator: String, } @@ -53,7 +51,7 @@ impl DefIdDirectory { DefIdDirectory { paths: vec![], krates: krates } } - fn max_current_crate(&self, tcx: TyCtxt) -> ast::CrateNum { + fn max_current_crate(&self, tcx: TyCtxt) -> CrateNum { tcx.sess.cstore.crates() .into_iter() .max() @@ -72,8 +70,8 @@ impl DefIdDirectory { pub fn krate_still_valid(&self, tcx: TyCtxt, - max_current_crate: ast::CrateNum, - krate: ast::CrateNum) -> bool { + max_current_crate: CrateNum, + krate: CrateNum) -> bool { // Check that the crate-number still matches. For now, if it // doesn't, just return None. We could do better, such as // finding the new number. @@ -81,7 +79,7 @@ impl DefIdDirectory { if krate > max_current_crate { false } else { - let old_info = &self.krates[krate as usize]; + let old_info = &self.krates[krate.as_usize()]; assert_eq!(old_info.krate, krate); let old_name: &str = &old_info.name; let old_disambiguator: &str = &old_info.disambiguator; @@ -101,7 +99,7 @@ impl DefIdDirectory { } else { debug!("crate {} changed from {:?} to {:?}/{:?}", path.krate, - self.krates[path.krate as usize], + self.krates[path.krate.as_usize()], tcx.crate_name(path.krate), tcx.crate_disambiguator(path.krate)); None diff --git a/src/librustc_incremental/persist/fs.rs b/src/librustc_incremental/persist/fs.rs index 8166045be5f6f..c9cfaf4f6613f 100644 --- a/src/librustc_incremental/persist/fs.rs +++ b/src/librustc_incremental/persist/fs.rs @@ -114,8 +114,8 @@ //! unsupported file system and emit a warning in that case. This is not yet //! implemented. +use rustc::hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc::hir::svh::Svh; -use rustc::middle::cstore::LOCAL_CRATE; use rustc::session::Session; use rustc::ty::TyCtxt; use rustc::util::fs as fs_util; @@ -129,7 +129,6 @@ use std::mem; use std::path::{Path, PathBuf}; use std::time::{UNIX_EPOCH, SystemTime, Duration}; use std::__rand::{thread_rng, Rng}; -use syntax::ast; const LOCK_FILE_EXT: &'static str = ".lock"; const DEP_GRAPH_FILENAME: &'static str = "dep-graph.bin"; @@ -580,7 +579,7 @@ fn string_to_timestamp(s: &str) -> Result { Ok(UNIX_EPOCH + duration) } -fn crate_path_tcx(tcx: TyCtxt, cnum: ast::CrateNum) -> PathBuf { +fn crate_path_tcx(tcx: TyCtxt, cnum: CrateNum) -> PathBuf { crate_path(tcx.sess, &tcx.crate_name(cnum), &tcx.crate_disambiguator(cnum)) } @@ -592,7 +591,7 @@ fn crate_path_tcx(tcx: TyCtxt, cnum: ast::CrateNum) -> PathBuf { /// crate's (name, disambiguator) pair. The metadata hashes are only valid for /// the exact version of the binary we are reading from now (i.e. the hashes /// are part of the dependency graph of a specific compilation session). -pub fn find_metadata_hashes_for(tcx: TyCtxt, cnum: ast::CrateNum) -> Option { +pub fn find_metadata_hashes_for(tcx: TyCtxt, cnum: CrateNum) -> Option { let crate_directory = crate_path_tcx(tcx, cnum); if !crate_directory.exists() { diff --git a/src/librustc_incremental/persist/hash.rs b/src/librustc_incremental/persist/hash.rs index bafaafd4afa0e..6dcf2c288914c 100644 --- a/src/librustc_incremental/persist/hash.rs +++ b/src/librustc_incremental/persist/hash.rs @@ -11,7 +11,7 @@ use rbml::Error; use rbml::opaque::Decoder; use rustc::dep_graph::DepNode; -use rustc::hir::def_id::DefId; +use rustc::hir::def_id::{CrateNum, DefId}; use rustc::hir::svh::Svh; use rustc::ty::TyCtxt; use rustc_data_structures::fnv::FnvHashMap; @@ -19,7 +19,6 @@ use rustc_data_structures::flock; use rustc_serialize::Decodable; use std::io::{ErrorKind, Read}; use std::fs::File; -use syntax::ast; use IncrementalHashesMap; use super::data::*; @@ -29,7 +28,7 @@ pub struct HashContext<'a, 'tcx: 'a> { pub tcx: TyCtxt<'a, 'tcx, 'tcx>, incremental_hashes_map: &'a IncrementalHashesMap, item_metadata_hashes: FnvHashMap, - crate_hashes: FnvHashMap, + crate_hashes: FnvHashMap, } impl<'a, 'tcx> HashContext<'a, 'tcx> { @@ -121,7 +120,7 @@ impl<'a, 'tcx> HashContext<'a, 'tcx> { } } - fn load_data(&mut self, cnum: ast::CrateNum) { + fn load_data(&mut self, cnum: CrateNum) { debug!("load_data(cnum={})", cnum); let svh = self.tcx.sess.cstore.crate_hash(cnum); @@ -187,7 +186,7 @@ impl<'a, 'tcx> HashContext<'a, 'tcx> { } fn load_from_data(&mut self, - cnum: ast::CrateNum, + cnum: CrateNum, data: &[u8], expected_svh: Svh) -> Result<(), Error> { debug!("load_from_data(cnum={})", cnum); diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index e8d9e90456efc..1209ced8dd3d7 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -92,7 +92,7 @@ pub struct TypeLimits { impl TypeLimits { pub fn new() -> TypeLimits { TypeLimits { - negated_expr_id: !0, + negated_expr_id: ast::DUMMY_NODE_ID, } } } diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs index 673a31c55abe0..397b33178dce8 100644 --- a/src/librustc_metadata/astencode.rs +++ b/src/librustc_metadata/astencode.rs @@ -9,98 +9,57 @@ // except according to those terms. #![allow(non_camel_case_types)] -// FIXME: remove this after snapshot, and Results are handled -#![allow(unused_must_use)] use rustc::hir::map as ast_map; -use rustc::hir; -use rustc::hir::fold; -use rustc::hir::fold::Folder; use rustc::hir::intravisit::{Visitor, IdRangeComputingVisitor, IdRange}; use common as c; use cstore; -use decoder; use decoder::DecodeContext; use encoder::EncodeContext; use middle::cstore::{InlinedItem, InlinedItemRef}; use rustc::ty::adjustment; -use rustc::ty::cast; -use middle::const_qualif::ConstQualif; -use rustc::hir::def::{self, Def}; +use rustc::hir::def; use rustc::hir::def_id::DefId; -use rustc::ty::{self, Ty, TyCtxt}; +use rustc::ty::{self, TyCtxt}; use syntax::ast; -use syntax::ptr::P; -use syntax_pos; - -use std::io::SeekFrom; -use std::io::prelude::*; use rbml::reader; use rbml; -use rustc_serialize::{Decodable, Decoder, DecoderHelpers}; -use rustc_serialize::{Encodable, EncoderHelpers}; - -trait tr { - fn tr(&self, dcx: &DecodeContext) -> Self; -} +use rustc_serialize::{Decodable, Encodable}; // ______________________________________________________________________ // Top-level methods. pub fn encode_inlined_item(ecx: &mut EncodeContext, ii: InlinedItemRef) { - let id = match ii { - InlinedItemRef::Item(_, i) => i.id, - InlinedItemRef::TraitItem(_, ti) => ti.id, - InlinedItemRef::ImplItem(_, ii) => ii.id, - }; - debug!("> Encoding inlined item: {} ({:?})", - ecx.tcx.node_path_str(id), - ecx.writer.seek(SeekFrom::Current(0))); - - // Folding could be avoided with a smarter encoder. - let (ii, expected_id_range) = simplify_ast(ii); - let id_range = inlined_item_id_range(&ii); - assert_eq!(expected_id_range, id_range); - - ecx.start_tag(c::tag_ast); - - ecx.start_tag(c::tag_id_range); - id_range.encode(&mut ecx.opaque()); - ecx.end_tag(); - - ecx.start_tag(c::tag_tree); - ii.encode(ecx); - ecx.end_tag(); - - encode_side_tables_for_ii(ecx, &ii); - ecx.end_tag(); + ecx.tag(c::tag_ast, |ecx| { + ecx.tag(c::tag_id_range, |ecx| { + let mut visitor = IdRangeComputingVisitor::new(); + match ii { + InlinedItemRef::Item(_, i) => visitor.visit_item(i), + InlinedItemRef::TraitItem(_, ti) => visitor.visit_trait_item(ti), + InlinedItemRef::ImplItem(_, ii) => visitor.visit_impl_item(ii) + } + visitor.result().encode(&mut ecx.opaque()).unwrap() + }); - debug!("< Encoded inlined fn: {} ({:?})", - ecx.tcx.node_path_str(id), - ecx.writer.seek(SeekFrom::Current(0))); -} + ecx.tag(c::tag_tree, |ecx| ii.encode(ecx).unwrap()); -impl<'a, 'b, 'tcx> ast_map::FoldOps for &'a DecodeContext<'b, 'tcx> { - fn new_id(&self, id: ast::NodeId) -> ast::NodeId { - if id == ast::DUMMY_NODE_ID { - // Used by ast_map to map the NodeInlinedParent. - self.tcx.sess.next_node_id() - } else { - self.tr_id(id) - } - } - fn new_def_id(&self, def_id: DefId) -> DefId { - self.tr_def_id(def_id) - } - fn new_span(&self, span: syntax_pos::Span) -> syntax_pos::Span { - self.tr_span(span) - } + ecx.tag(c::tag_table, |ecx| { + let mut visitor = SideTableEncodingIdVisitor { + ecx: ecx + }; + match ii { + InlinedItemRef::Item(_, i) => visitor.visit_item(i), + InlinedItemRef::TraitItem(_, ti) => visitor.visit_trait_item(ti), + InlinedItemRef::ImplItem(_, ii) => visitor.visit_impl_item(ii) + } + }); + }); } /// Decodes an item from its AST in the cdata's metadata and adds it to the @@ -113,8 +72,13 @@ pub fn decode_inlined_item<'a, 'tcx>(cdata: &cstore::CrateMetadata, orig_did: DefId) -> &'tcx InlinedItem { debug!("> Decoding inlined fn: {:?}", tcx.item_path_str(orig_did)); - let id_range_doc = ast_doc.get(c::tag_id_range); - let from_id_range = IdRange::decode(&mut id_range_doc.opaque()).unwrap(); + let from_id_range = { + let decoder = &mut ast_doc.get(c::tag_id_range).opaque(); + IdRange { + min: ast::NodeId::from_u32(u32::decode(decoder).unwrap()), + max: ast::NodeId::from_u32(u32::decode(decoder).unwrap()) + } + }; let mut dcx = DecodeContext::new(tcx, cdata, from_id_range, ast_doc.get(c::tag_tree)); let ii = InlinedItem::decode(&mut dcx).unwrap(); @@ -123,7 +87,7 @@ pub fn decode_inlined_item<'a, 'tcx>(cdata: &cstore::CrateMetadata, parent_def_path, parent_did, ii, - &dcx); + tcx.sess.next_node_id()); let item_node_id = match ii { &InlinedItem::Item(_, ref i) => i.id, @@ -138,376 +102,18 @@ pub fn decode_inlined_item<'a, 'tcx>(cdata: &cstore::CrateMetadata, ii } -// ______________________________________________________________________ -// Enumerating the IDs which appear in an AST - -impl<'a, 'tcx> DecodeContext<'a, 'tcx> { - /// Translates an internal id, meaning a node id that is known to refer to some part of the - /// item currently being inlined, such as a local variable or argument. All naked node-ids - /// that appear in types have this property, since if something might refer to an external item - /// we would use a def-id to allow for the possibility that the item resides in another crate. - pub fn tr_id(&self, id: ast::NodeId) -> ast::NodeId { - // from_id_range should be non-empty - assert!(!self.from_id_range.empty()); - // Make sure that translating the NodeId will actually yield a - // meaningful result - assert!(self.from_id_range.contains(id)); - - // Use wrapping arithmetic because otherwise it introduces control flow. - // Maybe we should just have the control flow? -- aatch - (id.wrapping_sub(self.from_id_range.min).wrapping_add(self.to_id_range.min)) - } - - /// Translates an EXTERNAL def-id, converting the crate number from the one used in the encoded - /// data to the current crate numbers.. By external, I mean that it be translated to a - /// reference to the item in its original crate, as opposed to being translated to a reference - /// to the inlined version of the item. This is typically, but not always, what you want, - /// because most def-ids refer to external things like types or other fns that may or may not - /// be inlined. Note that even when the inlined function is referencing itself recursively, we - /// would want `tr_def_id` for that reference--- conceptually the function calls the original, - /// non-inlined version, and trans deals with linking that recursive call to the inlined copy. - pub fn tr_def_id(&self, did: DefId) -> DefId { - decoder::translate_def_id(self.cdata, did) - } - - /// Translates a `Span` from an extern crate to the corresponding `Span` - /// within the local crate's codemap. - pub fn tr_span(&self, span: syntax_pos::Span) -> syntax_pos::Span { - decoder::translate_span(self.cdata, - self.tcx.sess.codemap(), - &self.last_filemap_index, - span) - } -} - -impl tr for DefId { - fn tr(&self, dcx: &DecodeContext) -> DefId { - dcx.tr_def_id(*self) - } -} - -impl tr for Option { - fn tr(&self, dcx: &DecodeContext) -> Option { - self.map(|d| dcx.tr_def_id(d)) - } -} - -impl tr for syntax_pos::Span { - fn tr(&self, dcx: &DecodeContext) -> syntax_pos::Span { - dcx.tr_span(*self) - } -} - -// ______________________________________________________________________ -// Encoding and decoding the AST itself -// -// When decoding, we have to renumber the AST so that the node ids that -// appear within are disjoint from the node ids in our existing ASTs. -// We also have to adjust the spans: for now we just insert a dummy span, -// but eventually we should add entries to the local codemap as required. - -struct NestedItemsDropper { - id_range: IdRange -} - -impl Folder for NestedItemsDropper { - - // The unit tests below run on HIR with NodeIds not properly assigned. That - // causes an integer overflow. So we just don't track the id_range when - // building the unit tests. - #[cfg(not(test))] - fn new_id(&mut self, id: ast::NodeId) -> ast::NodeId { - // Record the range of NodeIds we are visiting, so we can do a sanity - // check later - self.id_range.add(id); - id - } - - fn fold_block(&mut self, blk: P) -> P { - blk.and_then(|hir::Block {id, stmts, expr, rules, span, ..}| { - let stmts_sans_items = stmts.into_iter().filter_map(|stmt| { - let use_stmt = match stmt.node { - hir::StmtExpr(..) | hir::StmtSemi(..) => true, - hir::StmtDecl(ref decl, _) => { - match decl.node { - hir::DeclLocal(_) => true, - hir::DeclItem(_) => false, - } - } - }; - if use_stmt { - Some(stmt) - } else { - None - } - }).collect(); - let blk_sans_items = P(hir::Block { - stmts: stmts_sans_items, - expr: expr, - id: id, - rules: rules, - span: span, - }); - fold::noop_fold_block(blk_sans_items, self) - }) - } -} - -// Produces a simplified copy of the AST which does not include things -// that we do not need to or do not want to export. For example, we -// do not include any nested items: if these nested items are to be -// inlined, their AST will be exported separately (this only makes -// sense because, in Rust, nested items are independent except for -// their visibility). -// -// As it happens, trans relies on the fact that we do not export -// nested items, as otherwise it would get confused when translating -// inlined items. -fn simplify_ast(ii: InlinedItemRef) -> (InlinedItem, IdRange) { - let mut fld = NestedItemsDropper { - id_range: IdRange::max() - }; - - let ii = match ii { - // HACK we're not dropping items. - InlinedItemRef::Item(d, i) => { - InlinedItem::Item(d, P(fold::noop_fold_item(i.clone(), &mut fld))) - } - InlinedItemRef::TraitItem(d, ti) => { - InlinedItem::TraitItem(d, P(fold::noop_fold_trait_item(ti.clone(), &mut fld))) - } - InlinedItemRef::ImplItem(d, ii) => { - InlinedItem::ImplItem(d, P(fold::noop_fold_impl_item(ii.clone(), &mut fld))) - } - }; - - (ii, fld.id_range) -} - -// ______________________________________________________________________ -// Encoding and decoding of ast::def - -impl tr for Def { - fn tr(&self, dcx: &DecodeContext) -> Def { - match *self { - Def::Fn(did) => Def::Fn(did.tr(dcx)), - Def::Method(did) => Def::Method(did.tr(dcx)), - Def::SelfTy(opt_did, impl_id) => { - // Since the impl_id will never lie within the reserved range of - // imported NodeIds, it does not make sense to translate it. - // The result would not make any sense within the importing crate. - // We also don't allow for impl items to be inlined (just their - // members), so even if we had a DefId here, we wouldn't be able - // to do much with it. - // So, we set the id to DUMMY_NODE_ID. That way we make it - // explicit that this is no usable NodeId. - Def::SelfTy(opt_did.map(|did| did.tr(dcx)), - impl_id.map(|_| ast::DUMMY_NODE_ID)) - } - Def::Mod(did) => { Def::Mod(did.tr(dcx)) } - Def::ForeignMod(did) => { Def::ForeignMod(did.tr(dcx)) } - Def::Static(did, m) => { Def::Static(did.tr(dcx), m) } - Def::Const(did) => { Def::Const(did.tr(dcx)) } - Def::AssociatedConst(did) => Def::AssociatedConst(did.tr(dcx)), - Def::Local(_, nid) => { - let nid = dcx.tr_id(nid); - let did = dcx.tcx.map.local_def_id(nid); - Def::Local(did, nid) - } - Def::Variant(e_did, v_did) => Def::Variant(e_did.tr(dcx), v_did.tr(dcx)), - Def::Trait(did) => Def::Trait(did.tr(dcx)), - Def::Enum(did) => Def::Enum(did.tr(dcx)), - Def::TyAlias(did) => Def::TyAlias(did.tr(dcx)), - Def::AssociatedTy(trait_did, did) => - Def::AssociatedTy(trait_did.tr(dcx), did.tr(dcx)), - Def::PrimTy(p) => Def::PrimTy(p), - Def::TyParam(did) => Def::TyParam(did.tr(dcx)), - Def::Upvar(_, nid1, index, nid2) => { - let nid1 = dcx.tr_id(nid1); - let nid2 = dcx.tr_id(nid2); - let did1 = dcx.tcx.map.local_def_id(nid1); - Def::Upvar(did1, nid1, index, nid2) - } - Def::Struct(did) => Def::Struct(did.tr(dcx)), - Def::Union(did) => Def::Union(did.tr(dcx)), - Def::Label(nid) => Def::Label(dcx.tr_id(nid)), - Def::Err => Def::Err, - } - } -} - -// ______________________________________________________________________ -// Encoding and decoding of freevar information - -impl<'a, 'tcx> DecodeContext<'a, 'tcx> { - fn read_freevar_entry(&mut self) -> hir::Freevar { - hir::Freevar::decode(self).unwrap().tr(self) - } -} - -impl tr for hir::Freevar { - fn tr(&self, dcx: &DecodeContext) -> hir::Freevar { - hir::Freevar { - def: self.def.tr(dcx), - span: self.span.tr(dcx), - } - } -} - -// ______________________________________________________________________ -// Encoding and decoding of MethodCallee - -impl<'a, 'tcx> EncodeContext<'a, 'tcx> { - fn encode_method_callee(&mut self, - autoderef: u32, - method: &ty::MethodCallee<'tcx>) { - use rustc_serialize::Encoder; - - self.emit_struct("MethodCallee", 4, |this| { - this.emit_struct_field("autoderef", 0, |this| { - autoderef.encode(this) - }); - this.emit_struct_field("def_id", 1, |this| { - method.def_id.encode(this) - }); - this.emit_struct_field("ty", 2, |this| { - method.ty.encode(this) - }); - this.emit_struct_field("substs", 3, |this| { - method.substs.encode(this) - }) - }).unwrap(); - } -} - -impl<'a, 'tcx> DecodeContext<'a, 'tcx> { - fn read_method_callee(&mut self) -> (u32, ty::MethodCallee<'tcx>) { - self.read_struct("MethodCallee", 4, |this| { - let autoderef = this.read_struct_field("autoderef", 0, - Decodable::decode).unwrap(); - Ok((autoderef, ty::MethodCallee { - def_id: this.read_struct_field("def_id", 1, |this| { - DefId::decode(this).map(|d| d.tr(this)) - }).unwrap(), - ty: this.read_struct_field("ty", 2, |this| { - Ty::decode(this) - }).unwrap(), - substs: this.read_struct_field("substs", 3, |this| { - Decodable::decode(this) - }).unwrap() - })) - }).unwrap() - } -} - // ______________________________________________________________________ // Encoding and decoding the side tables impl<'a, 'tcx> EncodeContext<'a, 'tcx> { - fn emit_upvar_capture(&mut self, capture: &ty::UpvarCapture<'tcx>) { - use rustc_serialize::Encoder; - - self.emit_enum("UpvarCapture", |this| { - match *capture { - ty::UpvarCapture::ByValue => { - this.emit_enum_variant("ByValue", 1, 0, |_| Ok(())) - } - ty::UpvarCapture::ByRef(ty::UpvarBorrow { kind, region }) => { - this.emit_enum_variant("ByRef", 2, 0, |this| { - this.emit_enum_variant_arg(0, |this| kind.encode(this)); - this.emit_enum_variant_arg(1, |this| region.encode(this)) - }) - } - } - }).unwrap() - } - - fn emit_auto_adjustment(&mut self, adj: &adjustment::AutoAdjustment<'tcx>) { - use rustc_serialize::Encoder; - - self.emit_enum("AutoAdjustment", |this| { - match *adj { - adjustment::AdjustReifyFnPointer => { - this.emit_enum_variant("AdjustReifyFnPointer", 1, 0, |_| Ok(())) - } - - adjustment::AdjustUnsafeFnPointer => { - this.emit_enum_variant("AdjustUnsafeFnPointer", 2, 0, |_| { - Ok(()) - }) - } - - adjustment::AdjustMutToConstPointer => { - this.emit_enum_variant("AdjustMutToConstPointer", 3, 0, |_| { - Ok(()) - }) - } - - adjustment::AdjustDerefRef(ref auto_deref_ref) => { - this.emit_enum_variant("AdjustDerefRef", 4, 2, |this| { - this.emit_enum_variant_arg(0, - |this| Ok(this.emit_auto_deref_ref(auto_deref_ref))) - }) - } - - adjustment::AdjustNeverToAny(ref ty) => { - this.emit_enum_variant("AdjustNeverToAny", 5, 1, |this| { - this.emit_enum_variant_arg(0, |this| ty.encode(this)) - }) - } - } - }); - } - - fn emit_autoref(&mut self, autoref: &adjustment::AutoRef<'tcx>) { - use rustc_serialize::Encoder; - - self.emit_enum("AutoRef", |this| { - match autoref { - &adjustment::AutoPtr(r, m) => { - this.emit_enum_variant("AutoPtr", 0, 2, |this| { - this.emit_enum_variant_arg(0, |this| r.encode(this)); - this.emit_enum_variant_arg(1, |this| m.encode(this)) - }) - } - &adjustment::AutoUnsafe(m) => { - this.emit_enum_variant("AutoUnsafe", 1, 1, |this| { - this.emit_enum_variant_arg(0, |this| m.encode(this)) - }) - } - } - }); - } - - fn emit_auto_deref_ref(&mut self, auto_deref_ref: &adjustment::AutoDerefRef<'tcx>) { - use rustc_serialize::Encoder; - - self.emit_struct("AutoDerefRef", 2, |this| { - this.emit_struct_field("autoderefs", 0, |this| auto_deref_ref.autoderefs.encode(this)); - - this.emit_struct_field("autoref", 1, |this| { - this.emit_option(|this| { - match auto_deref_ref.autoref { - None => this.emit_option_none(), - Some(ref a) => this.emit_option_some(|this| Ok(this.emit_autoref(a))), - } - }) - }); - - this.emit_struct_field("unsize", 2, |this| { - auto_deref_ref.unsize.encode(this) - }) - }); - } - fn tag(&mut self, tag_id: usize, f: F) where F: FnOnce(&mut Self), { - self.start_tag(tag_id); + self.start_tag(tag_id).unwrap(); f(self); - self.end_tag(); + self.end_tag().unwrap(); } fn id(&mut self, id: ast::NodeId) { @@ -525,14 +131,6 @@ impl<'a, 'b, 'tcx, 'v> Visitor<'v> for SideTableEncodingIdVisitor<'a, 'b, 'tcx> } } -fn encode_side_tables_for_ii(ecx: &mut EncodeContext, ii: &InlinedItem) { - ecx.start_tag(c::tag_table); - ii.visit(&mut SideTableEncodingIdVisitor { - ecx: ecx - }); - ecx.end_tag(); -} - fn encode_side_tables_for_id(ecx: &mut EncodeContext, id: ast::NodeId) { let tcx = ecx.tcx; @@ -548,23 +146,21 @@ fn encode_side_tables_for_id(ecx: &mut EncodeContext, id: ast::NodeId) { if let Some(ty) = tcx.node_types().get(&id) { ecx.tag(c::tag_table_node_type, |ecx| { ecx.id(id); - ty.encode(ecx); + ty.encode(ecx).unwrap(); }) } if let Some(item_substs) = tcx.tables.borrow().item_substs.get(&id) { ecx.tag(c::tag_table_item_subst, |ecx| { ecx.id(id); - item_substs.substs.encode(ecx); + item_substs.substs.encode(ecx).unwrap(); }) } if let Some(fv) = tcx.freevars.borrow().get(&id) { ecx.tag(c::tag_table_freevars, |ecx| { ecx.id(id); - ecx.emit_from_vec(fv, |ecx, fv_entry| { - fv_entry.encode(ecx) - }); + fv.encode(ecx).unwrap(); }); for freevar in fv { @@ -582,8 +178,8 @@ fn encode_side_tables_for_id(ecx: &mut EncodeContext, id: ast::NodeId) { .get(&upvar_id) .unwrap() .clone(); - var_id.encode(ecx); - ecx.emit_upvar_capture(&upvar_capture); + var_id.encode(ecx).unwrap(); + upvar_capture.encode(ecx).unwrap(); }) } } @@ -592,7 +188,8 @@ fn encode_side_tables_for_id(ecx: &mut EncodeContext, id: ast::NodeId) { if let Some(method) = tcx.tables.borrow().method_map.get(&method_call) { ecx.tag(c::tag_table_method_map, |ecx| { ecx.id(id); - ecx.encode_method_callee(method_call.autoderef, method) + method_call.autoderef.encode(ecx).unwrap(); + method.encode(ecx).unwrap(); }) } @@ -604,7 +201,8 @@ fn encode_side_tables_for_id(ecx: &mut EncodeContext, id: ast::NodeId) { if let Some(method) = tcx.tables.borrow().method_map.get(&method_call) { ecx.tag(c::tag_table_method_map, |ecx| { ecx.id(id); - ecx.encode_method_callee(method_call.autoderef, method) + method_call.autoderef.encode(ecx).unwrap(); + method.encode(ecx).unwrap(); }) } } @@ -614,7 +212,7 @@ fn encode_side_tables_for_id(ecx: &mut EncodeContext, id: ast::NodeId) { ecx.tag(c::tag_table_adjustments, |ecx| { ecx.id(id); - ecx.emit_auto_adjustment(adjustment); + adjustment.encode(ecx).unwrap(); }) } @@ -633,180 +231,60 @@ fn encode_side_tables_for_id(ecx: &mut EncodeContext, id: ast::NodeId) { } } -impl<'a, 'tcx> DecodeContext<'a, 'tcx> { - fn read_upvar_capture(&mut self) -> ty::UpvarCapture<'tcx> { - self.read_enum("UpvarCapture", |this| { - let variants = ["ByValue", "ByRef"]; - this.read_enum_variant(&variants, |this, i| { - Ok(match i { - 1 => ty::UpvarCapture::ByValue, - 2 => ty::UpvarCapture::ByRef(ty::UpvarBorrow { - kind: this.read_enum_variant_arg(0, - |this| Decodable::decode(this)).unwrap(), - region: this.read_enum_variant_arg(1, - |this| Decodable::decode(this)).unwrap() - }), - _ => bug!("bad enum variant for ty::UpvarCapture") - }) - }) - }).unwrap() - } - fn read_auto_adjustment(&mut self) -> adjustment::AutoAdjustment<'tcx> { - self.read_enum("AutoAdjustment", |this| { - let variants = ["AdjustReifyFnPointer", "AdjustUnsafeFnPointer", - "AdjustMutToConstPointer", "AdjustDerefRef", - "AdjustNeverToAny"]; - this.read_enum_variant(&variants, |this, i| { - Ok(match i { - 1 => adjustment::AdjustReifyFnPointer, - 2 => adjustment::AdjustUnsafeFnPointer, - 3 => adjustment::AdjustMutToConstPointer, - 4 => { - let auto_deref_ref: adjustment::AutoDerefRef = - this.read_enum_variant_arg(0, - |this| Ok(this.read_auto_deref_ref())).unwrap(); - - adjustment::AdjustDerefRef(auto_deref_ref) - } - 5 => { - let ty: Ty<'tcx> = this.read_enum_variant_arg(0, |this| { - Ty::decode(this) - }).unwrap(); - - adjustment::AdjustNeverToAny(ty) - } - _ => bug!("bad enum variant for adjustment::AutoAdjustment") - }) - }) - }).unwrap() - } - - fn read_auto_deref_ref(&mut self) -> adjustment::AutoDerefRef<'tcx> { - self.read_struct("AutoDerefRef", 2, |this| { - Ok(adjustment::AutoDerefRef { - autoderefs: this.read_struct_field("autoderefs", 0, |this| { - Decodable::decode(this) - }).unwrap(), - autoref: this.read_struct_field("autoref", 1, |this| { - this.read_option(|this, b| { - if b { - Ok(Some(this.read_autoref())) - } else { - Ok(None) - } - }) - }).unwrap(), - unsize: this.read_struct_field("unsize", 2, |this| { - Decodable::decode(this) - }).unwrap(), - }) - }).unwrap() - } - - fn read_autoref(&mut self) -> adjustment::AutoRef<'tcx> { - self.read_enum("AutoRef", |this| { - let variants = ["AutoPtr", "AutoUnsafe"]; - this.read_enum_variant(&variants, |this, i| { - Ok(match i { - 0 => { - let r: &'tcx ty::Region = - this.read_enum_variant_arg(0, |this| { - Decodable::decode(this) - }).unwrap(); - let m: hir::Mutability = - this.read_enum_variant_arg(1, |this| { - Decodable::decode(this) - }).unwrap(); - - adjustment::AutoPtr(r, m) - } - 1 => { - let m: hir::Mutability = - this.read_enum_variant_arg(0, |this| Decodable::decode(this)).unwrap(); - - adjustment::AutoUnsafe(m) - } - _ => bug!("bad enum variant for adjustment::AutoRef") - }) - }) - }).unwrap() - } -} - fn decode_side_tables<'a, 'tcx>(dcx: &mut DecodeContext<'a, 'tcx>, ast_doc: rbml::Doc<'a>) { for (tag, entry_doc) in reader::docs(ast_doc.get(c::tag_table)) { dcx.rbml_r = reader::Decoder::new(entry_doc); - - let id0: ast::NodeId = Decodable::decode(dcx).unwrap(); - let id = dcx.tr_id(id0); - - debug!(">> Side table document with tag 0x{:x} \ - found for id {} (orig {})", - tag, id, id0); - + let id = Decodable::decode(dcx).unwrap(); + debug!("decode_side_tables: entry for id={}, tag=0x{:x}", id, tag); match tag { c::tag_table_def => { - let def = Def::decode(dcx).unwrap().tr(dcx); + let def = Decodable::decode(dcx).unwrap(); dcx.tcx.def_map.borrow_mut().insert(id, def::PathResolution::new(def)); } c::tag_table_node_type => { - let ty = Ty::decode(dcx).unwrap(); + let ty = Decodable::decode(dcx).unwrap(); dcx.tcx.node_type_insert(id, ty); } c::tag_table_item_subst => { - let item_substs = ty::ItemSubsts { - substs: Decodable::decode(dcx).unwrap() - }; - dcx.tcx.tables.borrow_mut().item_substs.insert( - id, item_substs); + let item_substs = Decodable::decode(dcx).unwrap(); + dcx.tcx.tables.borrow_mut().item_substs.insert(id, item_substs); } c::tag_table_freevars => { - let fv_info = dcx.read_to_vec(|dcx| { - Ok(dcx.read_freevar_entry()) - }).unwrap().into_iter().collect(); + let fv_info = Decodable::decode(dcx).unwrap(); dcx.tcx.freevars.borrow_mut().insert(id, fv_info); } c::tag_table_upvar_capture_map => { - let var_id = ast::NodeId::decode(dcx).unwrap(); let upvar_id = ty::UpvarId { - var_id: dcx.tr_id(var_id), + var_id: Decodable::decode(dcx).unwrap(), closure_expr_id: id }; - let ub = dcx.read_upvar_capture(); + let ub = Decodable::decode(dcx).unwrap(); dcx.tcx.tables.borrow_mut().upvar_capture_map.insert(upvar_id, ub); } c::tag_table_method_map => { - let (autoderef, method) = dcx.read_method_callee(); let method_call = ty::MethodCall { expr_id: id, - autoderef: autoderef + autoderef: Decodable::decode(dcx).unwrap() }; + let method = Decodable::decode(dcx).unwrap(); dcx.tcx.tables.borrow_mut().method_map.insert(method_call, method); } c::tag_table_adjustments => { - let adj = dcx.read_auto_adjustment(); + let adj = Decodable::decode(dcx).unwrap(); dcx.tcx.tables.borrow_mut().adjustments.insert(id, adj); } c::tag_table_cast_kinds => { - let cast_kind = cast::CastKind::decode(dcx).unwrap(); + let cast_kind = Decodable::decode(dcx).unwrap(); dcx.tcx.cast_kinds.borrow_mut().insert(id, cast_kind); } c::tag_table_const_qualif => { - let qualif = ConstQualif::decode(dcx).unwrap(); + let qualif = Decodable::decode(dcx).unwrap(); dcx.tcx.const_qualif_map.borrow_mut().insert(id, qualif); } _ => { - bug!("unknown tag found in side tables: {:x}", tag); + bug!("unknown tag found in side tables: 0x{:x}", tag); } } - - debug!(">< Side table doc loaded"); } } - -fn inlined_item_id_range(ii: &InlinedItem) -> IdRange { - let mut visitor = IdRangeComputingVisitor::new(); - ii.visit(&mut visitor); - visitor.result() -} diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index a1ade43f64750..2774ffdf6c772 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -16,7 +16,7 @@ use cstore::{self, CStore, CrateSource, MetadataBlob}; use decoder; use loader::{self, CratePaths}; -use rustc::hir::def_id::DefIndex; +use rustc::hir::def_id::{CrateNum, DefIndex}; use rustc::hir::svh::Svh; use rustc::dep_graph::{DepGraph, DepNode}; use rustc::session::{config, Session}; @@ -52,7 +52,7 @@ struct LocalCrateReader<'a> { pub struct CrateReader<'a> { sess: &'a Session, cstore: &'a CStore, - next_crate_num: ast::CrateNum, + next_crate_num: CrateNum, foreign_item_map: FnvHashMap>, local_crate_name: String, local_crate_config: ast::CrateConfig, @@ -152,7 +152,7 @@ impl PMDSource { } enum LoadResult { - Previous(ast::CrateNum), + Previous(CrateNum), Loaded(loader::Library), } @@ -208,7 +208,7 @@ impl<'a> CrateReader<'a> { } fn existing_match(&self, name: &str, hash: Option<&Svh>, kind: PathKind) - -> Option { + -> Option { let mut ret = None; self.cstore.iter_crate_data(|cnum, data| { if data.name != name { return } @@ -295,14 +295,14 @@ impl<'a> CrateReader<'a> { span: Span, lib: loader::Library, explicitly_linked: bool) - -> (ast::CrateNum, Rc, + -> (CrateNum, Rc, cstore::CrateSource) { info!("register crate `extern crate {} as {}`", name, ident); self.verify_no_symbol_conflicts(span, &lib.metadata); // Claim this crate number and cache it let cnum = self.next_crate_num; - self.next_crate_num += 1; + self.next_crate_num = CrateNum::from_u32(cnum.as_u32() + 1); // Stash paths for top-most crate locally if necessary. let crate_paths = if root.is_none() { @@ -370,7 +370,7 @@ impl<'a> CrateReader<'a> { span: Span, kind: PathKind, explicitly_linked: bool) - -> (ast::CrateNum, Rc, cstore::CrateSource) { + -> (CrateNum, Rc, cstore::CrateSource) { info!("resolving crate `extern crate {} as {}`", name, ident); let result = match self.existing_match(name, hash, kind) { Some(cnum) => LoadResult::Previous(cnum), @@ -447,9 +447,9 @@ impl<'a> CrateReader<'a> { } fn update_extern_crate(&mut self, - cnum: ast::CrateNum, + cnum: CrateNum, mut extern_crate: ExternCrate, - visited: &mut FnvHashSet<(ast::CrateNum, bool)>) + visited: &mut FnvHashSet<(CrateNum, bool)>) { if !visited.insert((cnum, extern_crate.direct)) { return } @@ -482,7 +482,7 @@ impl<'a> CrateReader<'a> { fn resolve_crate_deps(&mut self, root: &Option, cdata: &[u8], - krate: ast::CrateNum, + krate: CrateNum, span: Span) -> cstore::CrateNumMap { debug!("resolving deps of external crate"); @@ -500,11 +500,13 @@ impl<'a> CrateReader<'a> { (dep.cnum, local_cnum) }).collect(); - let max_cnum = map.values().cloned().max().unwrap_or(0); + let max_cnum = map.values().cloned().max().map(|cnum| cnum.as_u32()).unwrap_or(0); // we map 0 and all other holes in the map to our parent crate. The "additional" // self-dependencies should be harmless. - (0..max_cnum+1).map(|cnum| map.get(&cnum).cloned().unwrap_or(krate)).collect() + (0..max_cnum+1).map(|cnum| { + map.get(&CrateNum::from_u32(cnum)).cloned().unwrap_or(krate) + }).collect() } fn read_extension_crate(&mut self, span: Span, info: &CrateInfo) -> ExtensionCrate { @@ -875,7 +877,7 @@ impl<'a> CrateReader<'a> { } fn inject_dependency_if(&self, - krate: ast::CrateNum, + krate: CrateNum, what: &str, needs_dep: &Fn(&cstore::CrateMetadata) -> bool) { // don't perform this validation if the session has errors, as one of @@ -1113,7 +1115,7 @@ pub fn read_local_crates(sess: & Session, /// function. When an item from an external crate is later inlined into this /// crate, this correspondence information is used to translate the span /// information of the inlined item so that it refers the correct positions in -/// the local codemap (see `astencode::DecodeContext::tr_span()`). +/// the local codemap (see `>`). /// /// The import algorithm in the function below will reuse FileMaps already /// existing in the local codemap. For example, even if the FileMap of some diff --git a/src/librustc_metadata/csearch.rs b/src/librustc_metadata/csearch.rs index c37b2de751f96..a30a5743c34f2 100644 --- a/src/librustc_metadata/csearch.rs +++ b/src/librustc_metadata/csearch.rs @@ -20,7 +20,7 @@ use middle::cstore::{NativeLibraryKind, LinkMeta, LinkagePreference}; use rustc::hir::def; use middle::lang_items; use rustc::ty::{self, Ty, TyCtxt, VariantKind}; -use rustc::hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX}; +use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX}; use rustc::dep_graph::DepNode; use rustc::hir::map as hir_map; @@ -303,14 +303,14 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { decoder::is_typedef(&cdata, did.index) } - fn dylib_dependency_formats(&self, cnum: ast::CrateNum) - -> Vec<(ast::CrateNum, LinkagePreference)> + fn dylib_dependency_formats(&self, cnum: CrateNum) + -> Vec<(CrateNum, LinkagePreference)> { let cdata = self.get_crate_data(cnum); decoder::get_dylib_dependency_formats(&cdata) } - fn lang_items(&self, cnum: ast::CrateNum) -> Vec<(DefIndex, usize)> + fn lang_items(&self, cnum: CrateNum) -> Vec<(DefIndex, usize)> { let mut result = vec![]; let crate_data = self.get_crate_data(cnum); @@ -320,80 +320,80 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { result } - fn missing_lang_items(&self, cnum: ast::CrateNum) + fn missing_lang_items(&self, cnum: CrateNum) -> Vec { let cdata = self.get_crate_data(cnum); decoder::get_missing_lang_items(&cdata) } - fn is_staged_api(&self, cnum: ast::CrateNum) -> bool + fn is_staged_api(&self, cnum: CrateNum) -> bool { self.get_crate_data(cnum).staged_api } - fn is_explicitly_linked(&self, cnum: ast::CrateNum) -> bool + fn is_explicitly_linked(&self, cnum: CrateNum) -> bool { self.get_crate_data(cnum).explicitly_linked.get() } - fn is_allocator(&self, cnum: ast::CrateNum) -> bool + fn is_allocator(&self, cnum: CrateNum) -> bool { self.get_crate_data(cnum).is_allocator() } - fn is_panic_runtime(&self, cnum: ast::CrateNum) -> bool + fn is_panic_runtime(&self, cnum: CrateNum) -> bool { self.get_crate_data(cnum).is_panic_runtime() } - fn is_compiler_builtins(&self, cnum: ast::CrateNum) -> bool { + fn is_compiler_builtins(&self, cnum: CrateNum) -> bool { self.get_crate_data(cnum).is_compiler_builtins() } - fn panic_strategy(&self, cnum: ast::CrateNum) -> PanicStrategy { + fn panic_strategy(&self, cnum: CrateNum) -> PanicStrategy { self.get_crate_data(cnum).panic_strategy() } - fn crate_attrs(&self, cnum: ast::CrateNum) -> Vec + fn crate_attrs(&self, cnum: CrateNum) -> Vec { decoder::get_crate_attributes(self.get_crate_data(cnum).data()) } - fn crate_name(&self, cnum: ast::CrateNum) -> token::InternedString + fn crate_name(&self, cnum: CrateNum) -> token::InternedString { token::intern_and_get_ident(&self.get_crate_data(cnum).name[..]) } - fn original_crate_name(&self, cnum: ast::CrateNum) -> token::InternedString + fn original_crate_name(&self, cnum: CrateNum) -> token::InternedString { token::intern_and_get_ident(&self.get_crate_data(cnum).name()) } - fn extern_crate(&self, cnum: ast::CrateNum) -> Option + fn extern_crate(&self, cnum: CrateNum) -> Option { self.get_crate_data(cnum).extern_crate.get() } - fn crate_hash(&self, cnum: ast::CrateNum) -> Svh + fn crate_hash(&self, cnum: CrateNum) -> Svh { let cdata = self.get_crate_data(cnum); decoder::get_crate_hash(cdata.data()) } - fn crate_disambiguator(&self, cnum: ast::CrateNum) -> token::InternedString + fn crate_disambiguator(&self, cnum: CrateNum) -> token::InternedString { let cdata = self.get_crate_data(cnum); token::intern_and_get_ident(decoder::get_crate_disambiguator(cdata.data())) } - fn crate_struct_field_attrs(&self, cnum: ast::CrateNum) + fn crate_struct_field_attrs(&self, cnum: CrateNum) -> FnvHashMap> { decoder::get_struct_field_attrs(&self.get_crate_data(cnum)) } - fn plugin_registrar_fn(&self, cnum: ast::CrateNum) -> Option + fn plugin_registrar_fn(&self, cnum: CrateNum) -> Option { let cdata = self.get_crate_data(cnum); decoder::get_plugin_registrar_fn(cdata.data()).map(|index| DefId { @@ -402,24 +402,24 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { }) } - fn native_libraries(&self, cnum: ast::CrateNum) -> Vec<(NativeLibraryKind, String)> + fn native_libraries(&self, cnum: CrateNum) -> Vec<(NativeLibraryKind, String)> { let cdata = self.get_crate_data(cnum); decoder::get_native_libraries(&cdata) } - fn reachable_ids(&self, cnum: ast::CrateNum) -> Vec + fn reachable_ids(&self, cnum: CrateNum) -> Vec { let cdata = self.get_crate_data(cnum); decoder::get_reachable_ids(&cdata) } - fn is_no_builtins(&self, cnum: ast::CrateNum) -> bool { + fn is_no_builtins(&self, cnum: CrateNum) -> bool { attr::contains_name(&self.crate_attrs(cnum), "no_builtins") } fn def_index_for_def_key(&self, - cnum: ast::CrateNum, + cnum: CrateNum, def: DefKey) -> Option { let cdata = self.get_crate_data(cnum); @@ -488,7 +488,7 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { result } - fn crate_top_level_items(&self, cnum: ast::CrateNum) -> Vec + fn crate_top_level_items(&self, cnum: CrateNum) -> Vec { let mut result = vec![]; let crate_data = self.get_crate_data(cnum); @@ -651,7 +651,7 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { decoder::is_item_mir_available(&cdata, def.index) } - fn crates(&self) -> Vec + fn crates(&self) -> Vec { let mut result = vec![]; self.iter_crate_data(|cnum, _| result.push(cnum)); @@ -686,17 +686,17 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { encoder::encoded_ty(tcx, ty, def_id_to_string) } - fn used_crates(&self, prefer: LinkagePreference) -> Vec<(ast::CrateNum, Option)> + fn used_crates(&self, prefer: LinkagePreference) -> Vec<(CrateNum, Option)> { self.do_get_used_crates(prefer) } - fn used_crate_source(&self, cnum: ast::CrateNum) -> CrateSource + fn used_crate_source(&self, cnum: CrateNum) -> CrateSource { self.opt_used_crate_source(cnum).unwrap() } - fn extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option + fn extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option { self.do_extern_mod_stmt_cnum(emod_id) } @@ -738,7 +738,7 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { use rustc::middle::cstore::ChildItem; use std::collections::vec_deque::VecDeque; use std::collections::hash_map::Entry; - for cnum in 1 .. self.next_crate_num() { + for cnum in (1 .. self.next_crate_num().as_usize()).map(CrateNum::new) { let cdata = self.get_crate_data(cnum); match cdata.extern_crate.get() { diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index bc3d92c11a1ea..388620a2dafd3 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -22,7 +22,7 @@ use index; use loader; use rustc::dep_graph::DepGraph; -use rustc::hir::def_id::{DefIndex, DefId}; +use rustc::hir::def_id::{CrateNum, DefIndex, DefId}; use rustc::hir::map::DefKey; use rustc::hir::svh::Svh; use rustc::middle::cstore::ExternCrate; @@ -47,7 +47,7 @@ pub use middle::cstore::{CrateSource, LinkMeta}; // local crate numbers (as generated during this session). Each external // crate may refer to types in other external crates, and each has their // own crate numbers. -pub type CrateNumMap = IndexVec; +pub type CrateNumMap = IndexVec; pub enum MetadataBlob { MetadataVec(Bytes), @@ -75,7 +75,7 @@ pub struct CrateMetadata { pub data: MetadataBlob, pub cnum_map: RefCell, - pub cnum: ast::CrateNum, + pub cnum: CrateNum, pub codemap_import_info: RefCell>, pub staged_api: bool, @@ -105,9 +105,9 @@ pub struct CachedInlinedItem { pub struct CStore { pub dep_graph: DepGraph, - metas: RefCell>>, + metas: RefCell>>, /// Map from NodeId's of local extern crate statements to crate numbers - extern_mod_crate_map: RefCell>, + extern_mod_crate_map: RefCell>, used_crate_sources: RefCell>, used_libraries: RefCell>, used_link_args: RefCell>, @@ -135,25 +135,25 @@ impl CStore { } } - pub fn next_crate_num(&self) -> ast::CrateNum { - self.metas.borrow().len() as ast::CrateNum + 1 + pub fn next_crate_num(&self) -> CrateNum { + CrateNum::new(self.metas.borrow().len() + 1) } - pub fn get_crate_data(&self, cnum: ast::CrateNum) -> Rc { + pub fn get_crate_data(&self, cnum: CrateNum) -> Rc { self.metas.borrow().get(&cnum).unwrap().clone() } - pub fn get_crate_hash(&self, cnum: ast::CrateNum) -> Svh { + pub fn get_crate_hash(&self, cnum: CrateNum) -> Svh { let cdata = self.get_crate_data(cnum); decoder::get_crate_hash(cdata.data()) } - pub fn set_crate_data(&self, cnum: ast::CrateNum, data: Rc) { + pub fn set_crate_data(&self, cnum: CrateNum, data: Rc) { self.metas.borrow_mut().insert(cnum, data); } pub fn iter_crate_data(&self, mut i: I) where - I: FnMut(ast::CrateNum, &Rc), + I: FnMut(CrateNum, &Rc), { for (&k, v) in self.metas.borrow().iter() { i(k, v); @@ -162,7 +162,7 @@ impl CStore { /// Like `iter_crate_data`, but passes source paths (if available) as well. pub fn iter_crate_data_origins(&self, mut i: I) where - I: FnMut(ast::CrateNum, &CrateMetadata, Option), + I: FnMut(CrateNum, &CrateMetadata, Option), { for (&k, v) in self.metas.borrow().iter() { let origin = self.opt_used_crate_source(k); @@ -178,7 +178,7 @@ impl CStore { } } - pub fn opt_used_crate_source(&self, cnum: ast::CrateNum) + pub fn opt_used_crate_source(&self, cnum: CrateNum) -> Option { self.used_crate_sources.borrow_mut() .iter().find(|source| source.cnum == cnum).cloned() @@ -193,7 +193,7 @@ impl CStore { self.statically_included_foreign_items.borrow_mut().clear(); } - pub fn crate_dependencies_in_rpo(&self, krate: ast::CrateNum) -> Vec + pub fn crate_dependencies_in_rpo(&self, krate: CrateNum) -> Vec { let mut ordering = Vec::new(); self.push_dependencies_in_postorder(&mut ordering, krate); @@ -202,8 +202,8 @@ impl CStore { } pub fn push_dependencies_in_postorder(&self, - ordering: &mut Vec, - krate: ast::CrateNum) + ordering: &mut Vec, + krate: CrateNum) { if ordering.contains(&krate) { return } @@ -227,7 +227,7 @@ impl CStore { // topological sort of all crates putting the leaves at the right-most // positions. pub fn do_get_used_crates(&self, prefer: LinkagePreference) - -> Vec<(ast::CrateNum, Option)> { + -> Vec<(CrateNum, Option)> { let mut ordering = Vec::new(); for (&num, _) in self.metas.borrow().iter() { self.push_dependencies_in_postorder(&mut ordering, num); @@ -272,7 +272,7 @@ impl CStore { pub fn add_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId, - cnum: ast::CrateNum) { + cnum: CrateNum) { self.extern_mod_crate_map.borrow_mut().insert(emod_id, cnum); } @@ -284,7 +284,7 @@ impl CStore { self.statically_included_foreign_items.borrow().contains(&id) } - pub fn do_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option + pub fn do_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option { self.extern_mod_crate_map.borrow().get(&emod_id).cloned() } diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 10c2747ab1696..72e95804ce8e3 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -34,7 +34,7 @@ use rustc::session::config::PanicStrategy; use middle::cstore::{InlinedItem, LinkagePreference}; use middle::cstore::{DefLike, DlDef, DlField, DlImpl}; use rustc::hir::def::Def; -use rustc::hir::def_id::{DefId, DefIndex}; +use rustc::hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE}; use middle::lang_items; use rustc::ty::{ImplContainer, TraitContainer}; use rustc::ty::{self, AdtKind, Ty, TyCtxt, TypeFoldable, VariantKind}; @@ -42,11 +42,8 @@ use rustc::ty::subst::Substs; use rustc_const_math::ConstInt; -use rustc::mir; -use rustc::mir::visit::MutVisitor; -use rustc::mir::repr::Location; +use rustc::mir::repr::Mir; -use std::cell::Cell; use std::io; use std::ops::{Deref, DerefMut}; use std::rc::Rc; @@ -54,11 +51,10 @@ use std::str; use rbml::reader; use rbml; -use rustc_serialize::{Decodable, Decoder, SpecializedDecoder}; +use rustc_serialize::{Decodable, SpecializedDecoder}; use syntax::attr; use syntax::parse::token; -use syntax::ast; -use syntax::codemap; +use syntax::ast::{self, NodeId}; use syntax::print::pprust; use syntax_pos::{self, Span, BytePos, NO_EXPANSION}; @@ -66,10 +62,10 @@ pub struct DecodeContext<'a, 'tcx: 'a> { pub rbml_r: rbml::reader::Decoder<'a>, pub tcx: TyCtxt<'a, 'tcx, 'tcx>, pub cdata: &'a cstore::CrateMetadata, - pub from_id_range: IdRange, - pub to_id_range: IdRange, + from_id_range: IdRange, + to_id_range: IdRange, // Cache the last used filemap for translating spans as an optimization. - pub last_filemap_index: Cell, + last_filemap_index: usize, } impl<'a, 'tcx> DecodeContext<'a, 'tcx> { @@ -82,9 +78,9 @@ impl<'a, 'tcx> DecodeContext<'a, 'tcx> { let to_id_range = if from_id_range.empty() { from_id_range } else { - let cnt = from_id_range.max - from_id_range.min; + let cnt = from_id_range.max.as_usize() - from_id_range.min.as_usize(); let to_id_min = tcx.sess.reserve_node_ids(cnt); - let to_id_max = to_id_min + cnt; + let to_id_max = NodeId::new(to_id_min.as_usize() + cnt); IdRange { min: to_id_min, max: to_id_max } }; @@ -94,7 +90,7 @@ impl<'a, 'tcx> DecodeContext<'a, 'tcx> { tcx: tcx, from_id_range: from_id_range, to_id_range: to_id_range, - last_filemap_index: Cell::new(0) + last_filemap_index: 0 } } @@ -104,7 +100,7 @@ impl<'a, 'tcx> DecodeContext<'a, 'tcx> { self.read_opaque(|this, doc| { Ok(op(&mut TyDecoder::with_doc( this.tcx, this.cdata.cnum, doc, - &mut |d| this.tr_def_id(d)))) + &mut |d| translate_def_id(&this.cdata, d)))) }).unwrap() } } @@ -122,6 +118,93 @@ impl<'a, 'tcx> DerefMut for DecodeContext<'a, 'tcx> { } } +impl<'a, 'tcx> SpecializedDecoder for DecodeContext<'a, 'tcx> { + fn specialized_decode(&mut self) -> Result { + let id = u32::decode(self)?; + + // from_id_range should be non-empty + assert!(!self.from_id_range.empty()); + // Make sure that translating the NodeId will actually yield a + // meaningful result + if !self.from_id_range.contains(NodeId::from_u32(id)) { + bug!("NodeId::decode: {} out of DecodeContext range ({:?} -> {:?})", + id, self.from_id_range, self.to_id_range); + } + + // Use wrapping arithmetic because otherwise it introduces control flow. + // Maybe we should just have the control flow? -- aatch + Ok(NodeId::from_u32(id.wrapping_sub(self.from_id_range.min.as_u32()) + .wrapping_add(self.to_id_range.min.as_u32()))) + } +} + +impl<'a, 'tcx> SpecializedDecoder for DecodeContext<'a, 'tcx> { + fn specialized_decode(&mut self) -> Result { + let cnum = CrateNum::from_u32(u32::decode(self)?); + if cnum == LOCAL_CRATE { + Ok(self.cdata.cnum) + } else { + Ok(self.cdata.cnum_map.borrow()[cnum]) + } + } +} + +impl<'a, 'tcx> SpecializedDecoder for DecodeContext<'a, 'tcx> { + fn specialized_decode(&mut self) -> Result { + let lo = BytePos::decode(self)?; + let hi = BytePos::decode(self)?; + + let (lo, hi) = if lo > hi { + // Currently macro expansion sometimes produces invalid Span values + // where lo > hi. In order not to crash the compiler when trying to + // translate these values, let's transform them into something we + // can handle (and which will produce useful debug locations at + // least some of the time). + // This workaround is only necessary as long as macro expansion is + // not fixed. FIXME(#23480) + (lo, lo) + } else { + (lo, hi) + }; + + let imported_filemaps = self.cdata.imported_filemaps(&self.tcx.sess.codemap()); + let filemap = { + // Optimize for the case that most spans within a translated item + // originate from the same filemap. + let last_filemap = &imported_filemaps[self.last_filemap_index]; + + if lo >= last_filemap.original_start_pos && + lo <= last_filemap.original_end_pos && + hi >= last_filemap.original_start_pos && + hi <= last_filemap.original_end_pos { + last_filemap + } else { + let mut a = 0; + let mut b = imported_filemaps.len(); + + while b - a > 1 { + let m = (a + b) / 2; + if imported_filemaps[m].original_start_pos > lo { + b = m; + } else { + a = m; + } + } + + self.last_filemap_index = a; + &imported_filemaps[a] + } + }; + + 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(syntax_pos::mk_sp(lo, hi)) + } +} + // FIXME(#36588) These impls are horribly unsound as they allow // the caller to pick any lifetime for 'tcx, including 'static, // by using the unspecialized proxies to them. @@ -148,8 +231,8 @@ impl<'a, 'tcx> SpecializedDecoder<&'tcx ty::Region> for DecodeContext<'a, 'tcx> impl<'a, 'tcx> SpecializedDecoder> for DecodeContext<'a, 'tcx> { fn specialized_decode(&mut self) -> Result, Self::Error> { Ok(ty::ClosureSubsts { - func_substs: Decodable::decode(this)?, - upvar_tys: this.tcx.mk_type_list(Decodable::decode(this)?) + func_substs: Decodable::decode(self)?, + upvar_tys: self.tcx.mk_type_list(Decodable::decode(self)?) }) } } @@ -157,7 +240,6 @@ impl<'a, 'tcx> SpecializedDecoder> for DecodeContext<'a, impl<'a, 'tcx> SpecializedDecoder> for DecodeContext<'a, 'tcx> { fn specialized_decode(&mut self) -> Result, Self::Error> { let def_id = DefId::decode(self)?; - let def_id = translate_def_id(self.cdata, def_id); Ok(self.tcx.lookup_adt_def(def_id)) } } @@ -318,8 +400,10 @@ fn item_sort(item: rbml::Doc) -> Option { fn untranslated_def_id(d: rbml::Doc) -> DefId { let id = reader::doc_as_u64(d); - let index = DefIndex::new((id & 0xFFFF_FFFF) as usize); - DefId { krate: (id >> 32) as u32, index: index } + DefId { + krate: CrateNum::from_u32((id >> 32) as u32), + index: DefIndex::from_u32((id & 0xFFFF_FFFF) as u32) + } } fn translated_def_id(cdata: Cmd, d: rbml::Doc) -> DefId { @@ -744,7 +828,7 @@ fn each_child_of_item_or_crate(cdata: Cmd, mut get_crate_data: G, mut callback: F) where F: FnMut(DefLike, ast::Name, ty::Visibility), - G: FnMut(ast::CrateNum) -> Rc, + G: FnMut(CrateNum) -> Rc, { // Iterate over all children. for child_info_doc in reader::tagged_docs(item_doc, tag_mod_child) { @@ -806,7 +890,7 @@ fn each_child_of_item_or_crate(cdata: Cmd, /// Iterates over each child of the given item. pub fn each_child_of_item(cdata: Cmd, id: DefIndex, get_crate_data: G, callback: F) where F: FnMut(DefLike, ast::Name, ty::Visibility), - G: FnMut(ast::CrateNum) -> Rc, + G: FnMut(CrateNum) -> Rc, { // Find the item. let item_doc = match cdata.get_item(id) { @@ -820,7 +904,7 @@ pub fn each_child_of_item(cdata: Cmd, id: DefIndex, get_crate_data: G, cal /// Iterates over all the top-level crate items. pub fn each_top_level_item_of_crate(cdata: Cmd, get_crate_data: G, callback: F) where F: FnMut(DefLike, ast::Name, ty::Visibility), - G: FnMut(ast::CrateNum) -> Rc, + G: FnMut(CrateNum) -> Rc, { each_child_of_item(cdata, CRATE_DEF_INDEX, get_crate_data, callback) } @@ -894,52 +978,14 @@ pub fn is_item_mir_available<'tcx>(cdata: Cmd, id: DefIndex) -> bool { pub fn maybe_get_item_mir<'a, 'tcx>(cdata: Cmd, tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefIndex) - -> Option> { + -> Option> { let item_doc = cdata.lookup_item(id); - return reader::maybe_get_doc(item_doc, tag_mir as usize).map(|mir_doc| { - let mut dcx = DecodeContext::new(tcx, cdata, - IdRange { min: 0, max: 0 }, - mir_doc); - - let mut mir = Decodable::decode(&mut dcx).unwrap(); - - assert!(dcx.rbml_r.position() == mir_doc.end); - - let mut def_id_and_span_translator = MirDefIdAndSpanTranslator { - crate_metadata: cdata, - codemap: tcx.sess.codemap(), - last_filemap_index_hint: Cell::new(0), - }; - - def_id_and_span_translator.visit_mir(&mut mir); - for promoted in &mut mir.promoted { - def_id_and_span_translator.visit_mir(promoted); - } - - mir - }); - - struct MirDefIdAndSpanTranslator<'cdata, 'codemap> { - crate_metadata: Cmd<'cdata>, - codemap: &'codemap codemap::CodeMap, - last_filemap_index_hint: Cell - } - - impl<'v, 'cdata, 'codemap> mir::visit::MutVisitor<'v> - for MirDefIdAndSpanTranslator<'cdata, 'codemap> - { - fn visit_def_id(&mut self, def_id: &mut DefId, _: Location) { - *def_id = translate_def_id(self.crate_metadata, *def_id); - } - - fn visit_span(&mut self, span: &mut Span) { - *span = translate_span(self.crate_metadata, - self.codemap, - &self.last_filemap_index_hint, - *span); - } - } + reader::maybe_get_doc(item_doc, tag_mir).map(|mir_doc| { + let id_range = IdRange { min: NodeId::new(0), max: NodeId::new(0) }; + let mut dcx = DecodeContext::new(tcx, cdata, id_range, mir_doc); + Decodable::decode(&mut dcx).unwrap() + }) } fn get_explicit_self<'a, 'tcx>(item: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>) @@ -1225,7 +1271,7 @@ pub fn get_crate_attributes(data: &[u8]) -> Vec { #[derive(Clone)] pub struct CrateDep { - pub cnum: ast::CrateNum, + pub cnum: CrateNum, pub name: String, pub hash: Svh, pub explicitly_linked: bool, @@ -1246,7 +1292,7 @@ pub fn get_crate_deps(data: &[u8]) -> Vec { let doc = reader::get_doc(depdoc, tag_crate_dep_explicitly_linked); let explicitly_linked = reader::doc_as_u8(doc) != 0; CrateDep { - cnum: crate_num as u32 + 1, + cnum: CrateNum::new(crate_num + 1), name: name, hash: hash, explicitly_linked: explicitly_linked, @@ -1335,64 +1381,6 @@ fn reverse_translate_def_id(cdata: Cmd, did: DefId) -> Option { None } -/// Translates a `Span` from an extern crate to the corresponding `Span` -/// within the local crate's codemap. -pub fn translate_span(cdata: Cmd, - codemap: &codemap::CodeMap, - last_filemap_index_hint: &Cell, - span: syntax_pos::Span) - -> syntax_pos::Span { - let span = if span.lo > span.hi { - // Currently macro expansion sometimes produces invalid Span values - // where lo > hi. In order not to crash the compiler when trying to - // translate these values, let's transform them into something we - // can handle (and which will produce useful debug locations at - // least some of the time). - // This workaround is only necessary as long as macro expansion is - // not fixed. FIXME(#23480) - syntax_pos::mk_sp(span.lo, span.lo) - } else { - span - }; - - let imported_filemaps = cdata.imported_filemaps(&codemap); - let filemap = { - // Optimize for the case that most spans within a translated item - // originate from the same filemap. - let last_filemap_index = last_filemap_index_hint.get(); - let last_filemap = &imported_filemaps[last_filemap_index]; - - if span.lo >= last_filemap.original_start_pos && - span.lo <= last_filemap.original_end_pos && - span.hi >= last_filemap.original_start_pos && - span.hi <= last_filemap.original_end_pos { - last_filemap - } else { - let mut a = 0; - let mut b = imported_filemaps.len(); - - while b - a > 1 { - let m = (a + b) / 2; - if imported_filemaps[m].original_start_pos > span.lo { - b = m; - } else { - a = m; - } - } - - last_filemap_index_hint.set(a); - &imported_filemaps[a] - } - }; - - let lo = (span.lo - filemap.original_start_pos) + - filemap.translated_filemap.start_pos; - let hi = (span.hi - filemap.original_start_pos) + - filemap.translated_filemap.start_pos; - - syntax_pos::mk_sp(lo, hi) -} - pub fn each_inherent_implementation_for_type(cdata: Cmd, id: DefIndex, mut callback: F) @@ -1491,7 +1479,7 @@ pub fn get_macro_span(doc: rbml::Doc) -> Span { } pub fn get_dylib_dependency_formats(cdata: Cmd) - -> Vec<(ast::CrateNum, LinkagePreference)> + -> Vec<(CrateNum, LinkagePreference)> { let formats = reader::get_doc(rbml::Doc::new(cdata.data()), tag_dylib_dependency_formats); @@ -1503,7 +1491,7 @@ pub fn get_dylib_dependency_formats(cdata: Cmd) let mut split = spec.split(':'); let cnum = split.next().unwrap(); let link = split.next().unwrap(); - let cnum: ast::CrateNum = cnum.parse().unwrap(); + let cnum = CrateNum::new(cnum.parse().unwrap()); let cnum = cdata.cnum_map.borrow()[cnum]; result.push((cnum, if link == "d" { LinkagePreference::RequireDynamic diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 0f7765713c3c9..e493daab09103 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -23,7 +23,7 @@ use index::{self, IndexData}; use middle::cstore::{InlinedItemRef, LinkMeta}; use rustc::hir::def; -use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId}; +use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId}; use middle::dependency_format::Linkage; use rustc::dep_graph::DepNode; use rustc::traits::specialization_graph; @@ -42,7 +42,7 @@ use std::io::{Cursor, SeekFrom}; use std::ops::{Deref, DerefMut}; use std::rc::Rc; use std::u32; -use syntax::ast::{self, NodeId, Name, CRATE_NODE_ID, CrateNum}; +use syntax::ast::{self, NodeId, Name, CRATE_NODE_ID}; use syntax::attr; use syntax; use syntax_pos::BytePos; @@ -136,8 +136,7 @@ fn encode_family(ecx: &mut EncodeContext, c: char) { } pub fn def_to_u64(did: DefId) -> u64 { - assert!(did.index.as_u32() < u32::MAX); - (did.krate as u64) << 32 | (did.index.as_usize() as u64) + (did.krate.as_u32() as u64) << 32 | (did.index.as_u32() as u64) } pub fn def_to_string(_tcx: TyCtxt, did: DefId) -> String { @@ -1457,7 +1456,7 @@ fn encode_crate_deps(ecx: &mut EncodeContext, cstore: &cstore::CStore) { // Sanity-check the crate numbers let mut expected_cnum = 1; for &(n, _) in &deps { - assert_eq!(n, expected_cnum); + assert_eq!(n, CrateNum::new(expected_cnum)); expected_cnum += 1; } diff --git a/src/librustc_metadata/tydecode.rs b/src/librustc_metadata/tydecode.rs index bcaf1640bc41b..6d3b8571d3c3b 100644 --- a/src/librustc_metadata/tydecode.rs +++ b/src/librustc_metadata/tydecode.rs @@ -18,7 +18,7 @@ use rustc::hir; -use rustc::hir::def_id::{DefId, DefIndex}; +use rustc::hir::def_id::{CrateNum, DefId, DefIndex}; use middle::region; use rustc::ty::subst::{Kind, Substs}; use rustc::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable}; @@ -38,7 +38,7 @@ pub type DefIdConvert<'a> = &'a mut FnMut(DefId) -> DefId; pub struct TyDecoder<'a, 'tcx: 'a> { data: &'a [u8], - krate: ast::CrateNum, + krate: CrateNum, pos: usize, tcx: TyCtxt<'a, 'tcx, 'tcx>, conv_def_id: DefIdConvert<'a>, @@ -46,7 +46,7 @@ pub struct TyDecoder<'a, 'tcx: 'a> { impl<'a,'tcx> TyDecoder<'a,'tcx> { pub fn with_doc(tcx: TyCtxt<'a, 'tcx, 'tcx>, - crate_num: ast::CrateNum, + crate_num: CrateNum, doc: rbml::Doc<'a>, conv: DefIdConvert<'a>) -> TyDecoder<'a,'tcx> { @@ -54,7 +54,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { } pub fn new(data: &'a [u8], - crate_num: ast::CrateNum, + crate_num: CrateNum, pos: usize, tcx: TyCtxt<'a, 'tcx, 'tcx>, conv: DefIdConvert<'a>) @@ -258,9 +258,9 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { // May still be worth fixing though. 'C' => { assert_eq!(self.next(), '['); - let fn_id = self.parse_uint() as ast::NodeId; + let fn_id = ast::NodeId::new(self.parse_uint()); assert_eq!(self.next(), '|'); - let body_id = self.parse_uint() as ast::NodeId; + let body_id = ast::NodeId::new(self.parse_uint()); assert_eq!(self.next(), ']'); region::CodeExtentData::CallSiteScope { fn_id: fn_id, body_id: body_id @@ -269,25 +269,25 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { // This creates scopes with the wrong NodeId. (See note above.) 'P' => { assert_eq!(self.next(), '['); - let fn_id = self.parse_uint() as ast::NodeId; + let fn_id = ast::NodeId::new(self.parse_uint()); assert_eq!(self.next(), '|'); - let body_id = self.parse_uint() as ast::NodeId; + let body_id = ast::NodeId::new(self.parse_uint()); assert_eq!(self.next(), ']'); region::CodeExtentData::ParameterScope { fn_id: fn_id, body_id: body_id } } 'M' => { - let node_id = self.parse_uint() as ast::NodeId; + let node_id = ast::NodeId::new(self.parse_uint()); region::CodeExtentData::Misc(node_id) } 'D' => { - let node_id = self.parse_uint() as ast::NodeId; + let node_id = ast::NodeId::new(self.parse_uint()); region::CodeExtentData::DestructionScope(node_id) } 'B' => { assert_eq!(self.next(), '['); - let node_id = self.parse_uint() as ast::NodeId; + let node_id = ast::NodeId::new(self.parse_uint()); assert_eq!(self.next(), '|'); let first_stmt_index = self.parse_u32(); assert_eq!(self.next(), ']'); @@ -726,7 +726,7 @@ fn parse_defid(buf: &[u8]) -> DefId { let crate_num = match str::from_utf8(crate_part).ok().and_then(|s| { s.parse::().ok() }) { - Some(cn) => cn as ast::CrateNum, + Some(cn) => CrateNum::new(cn), None => bug!("internal error: parse_defid: crate number expected, found {:?}", crate_part) }; diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs index 7fda658185e07..e75a954319669 100644 --- a/src/librustc_mir/transform/type_check.rs +++ b/src/librustc_mir/transform/type_check.rs @@ -20,6 +20,7 @@ use rustc::mir::tcx::LvalueTy; use rustc::mir::transform::{MirPass, MirSource, Pass}; use rustc::mir::visit::{self, Visitor}; use std::fmt; +use syntax::ast; use syntax_pos::{Span, DUMMY_SP}; use rustc_data_structures::indexed_vec::Idx; @@ -673,7 +674,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { where T: fmt::Debug + TypeFoldable<'tcx> { let mut selcx = traits::SelectionContext::new(self.infcx); - let cause = traits::ObligationCause::misc(self.last_span, 0); + let cause = traits::ObligationCause::misc(self.last_span, ast::CRATE_NODE_ID); let traits::Normalized { value, obligations } = traits::normalize(&mut selcx, cause, value); diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 31893b0873c72..659edb86be166 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -49,14 +49,14 @@ use rustc::middle::cstore::MacroLoader; use rustc::session::Session; use rustc::lint; use rustc::hir::def::*; -use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId}; +use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId}; use rustc::ty; use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap}; use rustc::util::nodemap::{NodeMap, NodeSet, FnvHashMap, FnvHashSet}; use syntax::ext::hygiene::Mark; use syntax::ast::{self, FloatTy}; -use syntax::ast::{CRATE_NODE_ID, Name, NodeId, CrateNum, IntTy, UintTy}; +use syntax::ast::{CRATE_NODE_ID, Name, NodeId, IntTy, UintTy}; use syntax::parse::token::{self, keywords}; use syntax::util::lev_distance::find_best_match_for_name; diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 67ee4c307d3c3..e452a44cea587 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -135,7 +135,7 @@ struct ExpansionVisitor<'b, 'a: 'b> { impl<'a, 'b> ExpansionVisitor<'a, 'b> { fn visit_invoc(&mut self, id: ast::NodeId) { - assert_eq!(id, self.resolver.expansion_data.len() as u32); + assert_eq!(id.as_u32(), self.resolver.expansion_data.len() as u32); self.resolver.expansion_data.push(ExpansionData { module: self.current_module.clone(), }); diff --git a/src/librustc_save_analysis/data.rs b/src/librustc_save_analysis/data.rs index 4e03ea4218f0a..fc235aaf9276b 100644 --- a/src/librustc_save_analysis/data.rs +++ b/src/librustc_save_analysis/data.rs @@ -14,8 +14,8 @@ //! retrieve the data from a crate. use rustc::hir; -use rustc::hir::def_id::DefId; -use syntax::ast::{self, CrateNum, NodeId}; +use rustc::hir::def_id::{CrateNum, DefId}; +use syntax::ast::{self, NodeId}; use syntax_pos::Span; pub struct CrateData { diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 8820f3616d50d..37b31eda5a35a 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -29,7 +29,7 @@ use rustc::hir; use rustc::hir::def::Def; -use rustc::hir::def_id::DefId; +use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc::hir::map::{Node, NodeItem}; use rustc::session::Session; use rustc::ty::{self, TyCtxt, ImplOrTraitItem, ImplOrTraitItemContainer}; @@ -37,7 +37,7 @@ use rustc::ty::{self, TyCtxt, ImplOrTraitItem, ImplOrTraitItemContainer}; use std::collections::HashSet; use std::hash::*; -use syntax::ast::{self, NodeId, PatKind, Attribute}; +use syntax::ast::{self, NodeId, PatKind, Attribute, CRATE_NODE_ID}; use syntax::parse::token::{self, keywords}; use syntax::visit::{self, Visitor}; use syntax::print::pprust::{path_to_string, ty_to_string, bounds_to_string, generics_to_string}; @@ -95,7 +95,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { analysis: analysis, dumper: dumper, span: span_utils.clone(), - cur_scope: 0, + cur_scope: CRATE_NODE_ID, mac_defs: HashSet::new(), mac_uses: HashSet::new(), } @@ -124,7 +124,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { let lo_loc = self.span.sess.codemap().lookup_char_pos(c.span.lo); ExternalCrateData { name: c.name, - num: c.number, + num: CrateNum::from_u32(c.number), file_name: SpanUtils::make_path_string(&lo_loc.file.name), } }).collect(); @@ -252,7 +252,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { ref_id: None, span: *span, qualname: qualname.to_owned(), - scope: 0 + scope: CRATE_NODE_ID }.lower(self.tcx)); // write the other sub-paths @@ -368,7 +368,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { qualname: format!("{}::{}", qualname, path_to_string(p)), type_value: typ, value: String::new(), - scope: 0, + scope: CRATE_NODE_ID, parent: None, visibility: Visibility::Inherited, docs: String::new(), @@ -1044,7 +1044,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { qualname: format!("{}${}", path_to_string(p), id), value: value, type_value: typ, - scope: 0, + scope: CRATE_NODE_ID, parent: None, visibility: Visibility::Inherited, docs: String::new(), @@ -1239,7 +1239,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor for DumpVisitor<'l, 'tcx, 'll, D> let alias_span = self.span.span_for_last_ident(item.span); let cnum = match self.sess.cstore.extern_mod_stmt_cnum(item.id) { Some(cnum) => cnum, - None => 0, + None => LOCAL_CRATE, }; if !self.span.filter_generated(alias_span, item.span) { @@ -1478,7 +1478,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor for DumpVisitor<'l, 'tcx, 'll, D> qualname: format!("{}${}", path_to_string(p), id), value: value, type_value: typ, - scope: 0, + scope: CRATE_NODE_ID, parent: None, visibility: Visibility::Inherited, docs: String::new(), diff --git a/src/librustc_save_analysis/external_data.rs b/src/librustc_save_analysis/external_data.rs index 32280a5c9262a..5847575742342 100644 --- a/src/librustc_save_analysis/external_data.rs +++ b/src/librustc_save_analysis/external_data.rs @@ -8,10 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use rustc::hir::def_id::{DefId, DefIndex}; +use rustc::hir::def_id::{CrateNum, DefId, DefIndex}; use rustc::hir::map::Map; use rustc::ty::TyCtxt; -use syntax::ast::{CrateNum, NodeId}; +use syntax::ast::NodeId; use syntax::codemap::CodeMap; use syntax_pos::Span; @@ -28,7 +28,10 @@ pub fn make_def_id(id: NodeId, map: &Map) -> DefId { } pub fn null_def_id() -> DefId { - DefId { krate: u32::max_value(), index: DefIndex::from_u32(u32::max_value()) } + DefId { + krate: CrateNum::from_u32(u32::max_value()), + index: DefIndex::from_u32(u32::max_value()) + } } #[derive(Clone, Debug, RustcEncodable)] diff --git a/src/librustc_save_analysis/json_api_dumper.rs b/src/librustc_save_analysis/json_api_dumper.rs index 78eaa65872a4c..d56aae18a7cd1 100644 --- a/src/librustc_save_analysis/json_api_dumper.rs +++ b/src/librustc_save_analysis/json_api_dumper.rs @@ -117,7 +117,7 @@ struct Id { impl From for Id { fn from(id: DefId) -> Id { Id { - krate: id.krate, + krate: id.krate.as_u32(), index: id.index.as_u32(), } } diff --git a/src/librustc_save_analysis/json_dumper.rs b/src/librustc_save_analysis/json_dumper.rs index 75abff8d37edb..0378d75cc6eb1 100644 --- a/src/librustc_save_analysis/json_dumper.rs +++ b/src/librustc_save_analysis/json_dumper.rs @@ -120,7 +120,7 @@ struct Id { impl From for Id { fn from(id: DefId) -> Id { Id { - krate: id.krate, + krate: id.krate.as_u32(), index: id.index.as_u32(), } } diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 51274068b26ca..3764e26b020db 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -52,7 +52,7 @@ use std::env; use std::fs::{self, File}; use std::path::{Path, PathBuf}; -use syntax::ast::{self, NodeId, PatKind, Attribute}; +use syntax::ast::{self, NodeId, PatKind, Attribute, CRATE_NODE_ID}; use syntax::parse::lexer::comments::strip_doc_comment_decoration; use syntax::parse::token::{self, keywords, InternedString}; use syntax::visit::{self, Visitor}; @@ -120,7 +120,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { }; result.push(CrateData { name: (&self.tcx.sess.cstore.crate_name(n)[..]).to_owned(), - number: n, + number: n.as_u32(), span: span, }); } @@ -676,7 +676,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { #[inline] pub fn enclosing_scope(&self, id: NodeId) -> NodeId { - self.tcx.map.get_enclosing_scope(id).unwrap_or(0) + self.tcx.map.get_enclosing_scope(id).unwrap_or(CRATE_NODE_ID) } } diff --git a/src/librustc_trans/adt.rs b/src/librustc_trans/adt.rs index 67e5ec2616d29..2b92d7e9e457c 100644 --- a/src/librustc_trans/adt.rs +++ b/src/librustc_trans/adt.rs @@ -556,9 +556,9 @@ fn range_to_inttype(cx: &CrateContext, hint: Hint, bounds: &IntBounds) -> IntTyp let attempts; match hint { - attr::ReprInt(span, ity) => { + attr::ReprInt(ity) => { if !bounds_usable(cx, ity, bounds) { - span_bug!(span, "representation hint insufficient for discriminant range") + bug!("representation hint insufficient for discriminant range") } return ity; } diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index 288249a7d9934..201e1e5f2ec4c 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -26,6 +26,7 @@ use CrateTranslation; use util::common::time; use util::fs::fix_windows_verbatim_for_gcc; use rustc::dep_graph::DepNode; +use rustc::hir::def_id::CrateNum; use rustc::hir::svh::Svh; use rustc_back::tempdir::TempDir; use rustc_incremental::IncrementalHashesMap; @@ -288,7 +289,7 @@ pub fn filename_for_input(sess: &Session, } pub fn each_linked_rlib(sess: &Session, - f: &mut FnMut(ast::CrateNum, &Path)) { + f: &mut FnMut(CrateNum, &Path)) { let crates = sess.cstore.used_crates(LinkagePreference::RequireStatic).into_iter(); let fmts = sess.dependency_formats.borrow(); let fmts = fmts.get(&config::CrateTypeExecutable) @@ -299,7 +300,7 @@ pub fn each_linked_rlib(sess: &Session, bug!("could not find formats for rlibs") }); for (cnum, path) in crates { - match fmts[cnum as usize - 1] { + match fmts[cnum.as_usize() - 1] { Linkage::NotLinked | Linkage::IncludedFromDylib => continue, _ => {} } @@ -933,7 +934,7 @@ fn add_upstream_rust_crates(cmd: &mut Linker, // appear statically in an existing dylib, meaning we'll pick up all the // symbols from the dylib. let src = sess.cstore.used_crate_source(cnum); - match data[cnum as usize - 1] { + match data[cnum.as_usize() - 1] { // compiler-builtins are always placed last to ensure that they're // linked correctly. _ if sess.cstore.is_compiler_builtins(cnum) => { @@ -1003,7 +1004,7 @@ fn add_upstream_rust_crates(cmd: &mut Linker, sess: &Session, tmpdir: &Path, crate_type: config::CrateType, - cnum: ast::CrateNum) { + cnum: CrateNum) { let src = sess.cstore.used_crate_source(cnum); let cratepath = &src.rlib.unwrap().0; if !sess.lto() && crate_type != config::CrateTypeDylib { diff --git a/src/librustc_trans/back/linker.rs b/src/librustc_trans/back/linker.rs index 58cad5c117f93..dd14f98c9207f 100644 --- a/src/librustc_trans/back/linker.rs +++ b/src/librustc_trans/back/linker.rs @@ -21,10 +21,10 @@ use monomorphize::Instance; use back::archive; use middle::dependency_format::Linkage; +use rustc::hir::def_id::CrateNum; use session::Session; use session::config::CrateType; use session::config; -use syntax::ast; /// For all the linkers we support, and information they might /// need out of the shared crate context before we get rid of it. @@ -473,7 +473,7 @@ fn exported_symbols(scx: &SharedCrateContext, let deps = formats[&crate_type].iter(); symbols.extend(deps.enumerate().filter_map(|(i, f)| { if *f == Linkage::Static { - Some((i + 1) as ast::CrateNum) + Some(CrateNum::new(i + 1)) } else { None } diff --git a/src/librustc_back/rpath.rs b/src/librustc_trans/back/rpath.rs similarity index 98% rename from src/librustc_back/rpath.rs rename to src/librustc_trans/back/rpath.rs index 6cba27fcf3406..4ed860bd40d86 100644 --- a/src/librustc_back/rpath.rs +++ b/src/librustc_trans/back/rpath.rs @@ -12,10 +12,11 @@ use std::collections::HashSet; use std::env; use std::path::{Path, PathBuf}; use std::fs; -use syntax::ast; + +use rustc::hir::def_id::CrateNum; pub struct RPathConfig<'a> { - pub used_crates: Vec<(ast::CrateNum, Option)>, + pub used_crates: Vec<(CrateNum, Option)>, pub out_filename: PathBuf, pub is_like_osx: bool, pub has_rpath: bool, diff --git a/src/librustc_trans/back/symbol_names.rs b/src/librustc_trans/back/symbol_names.rs index 76d83eee4bb41..ab1474c235132 100644 --- a/src/librustc_trans/back/symbol_names.rs +++ b/src/librustc_trans/back/symbol_names.rs @@ -101,8 +101,8 @@ use common::{CrateContext, SharedCrateContext, gensym_name}; use monomorphize::Instance; use util::sha2::{Digest, Sha256}; -use rustc::middle::{cstore, weak_lang_items}; -use rustc::hir::def_id::DefId; +use rustc::middle::weak_lang_items; +use rustc::hir::def_id::{DefId, LOCAL_CRATE}; use rustc::hir::map as hir_map; use rustc::ty::{Ty, TyCtxt, TypeFoldable}; use rustc::ty::item_path::{self, ItemPathBuffer, RootMode}; @@ -298,7 +298,7 @@ pub fn exported_name_from_type_and_prefix<'a, 'tcx>(scx: &SharedCrateContext<'a, -> String { let empty_def_path = DefPath { data: vec![], - krate: cstore::LOCAL_CRATE, + krate: LOCAL_CRATE, }; let hash = get_symbol_hash(scx, &empty_def_path, t, None); let path = [token::intern_and_get_ident(prefix)]; @@ -315,7 +315,7 @@ pub fn internal_name_from_type_and_suffix<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx> gensym_name(suffix).as_str()]; let def_path = DefPath { data: vec![], - krate: cstore::LOCAL_CRATE, + krate: LOCAL_CRATE, }; let hash = get_symbol_hash(ccx.shared(), &def_path, t, None); mangle(path.iter().cloned(), Some(&hash[..])) diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index 3e60369acbff3..41c8d565d418c 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -69,7 +69,6 @@ pub use base::trans_crate; pub use disr::Disr; pub mod back { - pub use rustc_back::rpath; pub use rustc::hir::svh; pub mod archive; @@ -79,6 +78,7 @@ pub mod back { pub mod symbol_names; pub mod write; pub mod msvc; + pub mod rpath; } pub mod diagnostics; diff --git a/src/librustc_trans/type_of.rs b/src/librustc_trans/type_of.rs index 3873c24a9f676..141b8506c39b8 100644 --- a/src/librustc_trans/type_of.rs +++ b/src/librustc_trans/type_of.rs @@ -356,7 +356,7 @@ fn llvm_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, format!("{}<{}>", base, strings.join(", ")) }; - if did.krate == 0 { + if did.is_local() { tstr } else { format!("{}.{}", did.krate, tstr) diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index 5bd4f13a1119c..d1fb0736d2115 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -12,9 +12,8 @@ use super::{DeferredCallResolution, Expectation, FnCtxt, TupleArgumentsFlag}; use CrateCtxt; -use middle::cstore::LOCAL_CRATE; use hir::def::Def; -use hir::def_id::DefId; +use hir::def_id::{DefId, LOCAL_CRATE}; use rustc::{infer, traits}; use rustc::ty::{self, LvaluePreference, Ty}; use syntax::parse::token; diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index faad3f9b000cc..4a631493398e9 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -577,7 +577,7 @@ pub fn compare_const_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, assoc::normalize_associated_types_in(&infcx, &mut fulfillment_cx, impl_c_span, - 0, + ast::CRATE_NODE_ID, &impl_ty); debug!("compare_const_impl: impl_ty={:?}", @@ -587,7 +587,7 @@ pub fn compare_const_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, assoc::normalize_associated_types_in(&infcx, &mut fulfillment_cx, impl_c_span, - 0, + ast::CRATE_NODE_ID, &trait_ty); debug!("compare_const_impl: trait_ty={:?}", diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index baa084212a2d9..01d7b1e54751c 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -83,9 +83,8 @@ use self::TupleArgumentsFlag::*; use astconv::{AstConv, ast_region_to_region, PathParamMode}; use dep_graph::DepNode; use fmt_macros::{Parser, Piece, Position}; -use middle::cstore::LOCAL_CRATE; use hir::def::{Def, PathResolution}; -use hir::def_id::DefId; +use hir::def_id::{DefId, LOCAL_CRATE}; use hir::pat_util; use rustc::infer::{self, InferCtxt, InferOk, TypeOrigin, TypeTrace, type_variable}; use rustc::ty::subst::{Subst, Substs}; @@ -1450,7 +1449,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { writeback_errors: Cell::new(false), err_count_on_creation: inh.tcx.sess.err_count(), ret_ty: rty, - ps: RefCell::new(UnsafetyState::function(hir::Unsafety::Normal, 0)), + ps: RefCell::new(UnsafetyState::function(hir::Unsafety::Normal, + ast::CRATE_NODE_ID)), inh: inh, } } @@ -2117,7 +2117,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { .unwrap_or(type_variable::Default { ty: self.next_ty_var(), origin_span: syntax_pos::DUMMY_SP, - def_id: self.tcx.map.local_def_id(0) // what do I put here? + // what do I put here? + def_id: self.tcx.map.local_def_id(ast::CRATE_NODE_ID) }); // This is to ensure that we elimnate any non-determinism from the error diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs index d1eb0f995de13..70342a0cd258e 100644 --- a/src/librustc_typeck/coherence/orphan.rs +++ b/src/librustc_typeck/coherence/orphan.rs @@ -11,8 +11,7 @@ //! Orphan checker: every impl either implements a trait defined in this //! crate or pertains to a type defined in this crate. -use middle::cstore::LOCAL_CRATE; -use hir::def_id::DefId; +use hir::def_id::{DefId, LOCAL_CRATE}; use rustc::traits; use rustc::ty::{self, TyCtxt}; use syntax::ast; diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index b9dc75cdd9f12..7ee173019a516 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -37,7 +37,7 @@ use rustc::middle::cstore; use rustc::middle::privacy::AccessLevels; use rustc::middle::resolve_lifetime::DefRegion::*; use rustc::hir::def::Def; -use rustc::hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX}; +use rustc::hir::def_id::{self, DefId, DefIndex, CRATE_DEF_INDEX}; use rustc::hir::fold::Folder; use rustc::hir::print as pprust; use rustc::ty::subst::Substs; @@ -116,7 +116,7 @@ pub struct Crate { pub name: String, pub src: PathBuf, pub module: Option, - pub externs: Vec<(ast::CrateNum, ExternalCrate)>, + pub externs: Vec<(def_id::CrateNum, ExternalCrate)>, pub primitives: Vec, pub access_levels: Arc>, // These are later on moved into `CACHEKEY`, leaving the map empty. @@ -124,7 +124,7 @@ pub struct Crate { pub external_traits: FnvHashMap, } -struct CrateNum(ast::CrateNum); +struct CrateNum(def_id::CrateNum); impl<'a, 'tcx> Clean for visit_ast::RustdocVisitor<'a, 'tcx> { fn clean(&self, cx: &DocContext) -> Crate { @@ -1159,7 +1159,7 @@ impl<'a, 'tcx> Clean for (DefId, &'a ty::PolyFnSig<'tcx>) { values: sig.0.inputs.iter().map(|t| { Argument { type_: t.clean(cx), - id: 0, + id: ast::CRATE_NODE_ID, name: names.next().unwrap_or("".to_string()), } }).collect(), @@ -1808,7 +1808,7 @@ impl<'tcx> Clean for ty::Ty<'tcx> { type_params: Vec::new(), where_predicates: Vec::new() }, - decl: (cx.map.local_def_id(0), &fty.sig).clean(cx), + decl: (cx.map.local_def_id(ast::CRATE_NODE_ID), &fty.sig).clean(cx), abi: fty.abi, }), ty::TyAdt(def, substs) => { @@ -2590,7 +2590,7 @@ impl Clean> for doctree::Import { name: None, attrs: self.attrs.clean(cx), source: self.whence.clean(cx), - def_id: cx.map.local_def_id(0), + def_id: cx.map.local_def_id(ast::CRATE_NODE_ID), visibility: self.vis.clean(cx), stability: None, deprecation: None, diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 1e3804955e940..ab6858a09310f 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -13,7 +13,7 @@ use rustc_lint; use rustc_driver::{driver, target_features, abort_on_err}; use rustc::dep_graph::DepGraph; use rustc::session::{self, config}; -use rustc::hir::def_id::DefId; +use rustc::hir::def_id::{CrateNum, DefId}; use rustc::middle::privacy::AccessLevels; use rustc::ty::{self, TyCtxt}; use rustc::hir::map as hir_map; @@ -23,7 +23,7 @@ use rustc_trans::back::link; use rustc_resolve as resolve; use rustc_metadata::cstore::CStore; -use syntax::{ast, codemap}; +use syntax::codemap; use syntax::feature_gate::UnstableFeatures; use errors; use errors::emitter::ColorConfig; @@ -51,7 +51,7 @@ pub struct DocContext<'a, 'tcx: 'a> { pub map: &'a hir_map::Map<'tcx>, pub maybe_typed: MaybeTyped<'a, 'tcx>, pub input: Input, - pub populated_crate_impls: RefCell>, + pub populated_crate_impls: RefCell>, pub deref_trait_did: Cell>, pub deref_mut_trait_did: Cell>, // Note that external items for which `doc(hidden)` applies to are shown as diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs index c2404f4294e96..609ae0c0e6daf 100644 --- a/src/librustdoc/doctree.rs +++ b/src/librustdoc/doctree.rs @@ -21,6 +21,7 @@ use syntax::ptr::P; use syntax_pos::{self, Span}; use rustc::hir; +use rustc::hir::def_id::CrateNum; pub struct Module { pub name: Option, @@ -53,7 +54,7 @@ impl Module { pub fn new(name: Option) -> Module { Module { name : name, - id: 0, + id: ast::CRATE_NODE_ID, vis: hir::Inherited, stab: None, depr: None, @@ -245,7 +246,7 @@ pub struct Macro { pub struct ExternCrate { pub name: Name, - pub cnum: ast::CrateNum, + pub cnum: CrateNum, pub path: Option, pub vis: hir::Visibility, pub attrs: hir::HirVec, diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 65992798ab099..adcdc7aaab400 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -18,8 +18,7 @@ use std::fmt; use std::iter::repeat; -use rustc::middle::cstore::LOCAL_CRATE; -use rustc::hir::def_id::DefId; +use rustc::hir::def_id::{DefId, LOCAL_CRATE}; use syntax::abi::Abi; use rustc::hir; diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 8cc9bbb422ae6..03d772d1a6db3 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -53,10 +53,9 @@ use std::sync::Arc; use externalfiles::ExternalHtml; use serialize::json::{ToJson, Json, as_json}; -use syntax::{abi, ast}; +use syntax::abi; use syntax::feature_gate::UnstableFeatures; -use rustc::middle::cstore::LOCAL_CRATE; -use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId}; +use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, LOCAL_CRATE}; use rustc::middle::privacy::AccessLevels; use rustc::middle::stability; use rustc::session::config::get_unstable_features_setting; @@ -246,10 +245,10 @@ pub struct Cache { pub implementors: FnvHashMap>, /// Cache of where external crate documentation can be found. - pub extern_locations: FnvHashMap, + pub extern_locations: FnvHashMap, /// Cache of where documentation for primitives can be found. - pub primitive_locations: FnvHashMap, + pub primitive_locations: FnvHashMap, // Note that external items for which `doc(hidden)` applies to are shown as // non-reachable while local items aren't. This is because we're reusing diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 16a6e994b5a0b..a29566f7a0717 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -20,6 +20,7 @@ use syntax_pos::Span; use rustc::hir::map as hir_map; use rustc::hir::def::Def; +use rustc::hir::def_id::LOCAL_CRATE; use rustc::middle::privacy::AccessLevel; use rustc::util::nodemap::FnvHashSet; @@ -339,7 +340,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { let cstore = &self.cx.sess().cstore; om.extern_crates.push(ExternCrate { cnum: cstore.extern_mod_stmt_cnum(item.id) - .unwrap_or(ast::CrateNum::max_value()), + .unwrap_or(LOCAL_CRATE), name: name, path: p.map(|x|x.to_string()), vis: item.vis.clone(), diff --git a/src/librustdoc/visit_lib.rs b/src/librustdoc/visit_lib.rs index 3af030706b739..cbc556730fb63 100644 --- a/src/librustdoc/visit_lib.rs +++ b/src/librustdoc/visit_lib.rs @@ -11,9 +11,8 @@ use rustc::middle::cstore::{CrateStore, ChildItem, DefLike}; use rustc::middle::privacy::{AccessLevels, AccessLevel}; use rustc::hir::def::Def; -use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId}; +use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId}; use rustc::ty::Visibility; -use syntax::ast; use std::cell::RefMut; @@ -42,7 +41,7 @@ impl<'a, 'b, 'tcx> LibEmbargoVisitor<'a, 'b, 'tcx> { } } - pub fn visit_lib(&mut self, cnum: ast::CrateNum) { + pub fn visit_lib(&mut self, cnum: CrateNum) { let did = DefId { krate: cnum, index: CRATE_DEF_INDEX }; self.update(did, Some(AccessLevel::Public)); self.visit_mod(did); diff --git a/src/libserialize/lib.rs b/src/libserialize/lib.rs index ebd939120973d..7082ee5d292df 100644 --- a/src/libserialize/lib.rs +++ b/src/libserialize/lib.rs @@ -45,8 +45,7 @@ Core encoding and decoding interfaces. extern crate rustc_unicode; extern crate collections; -pub use self::serialize::{Decoder, Encoder, Decodable, Encodable, - DecoderHelpers, EncoderHelpers}; +pub use self::serialize::{Decoder, Encoder, Decodable, Encodable}; pub use self::serialize::{SpecializationError, SpecializedEncoder, SpecializedDecoder}; pub use self::serialize::{UseSpecializedEncodable, UseSpecializedDecodable}; diff --git a/src/libserialize/serialize.rs b/src/libserialize/serialize.rs index 4414fee78788e..ba6eefe82bbc6 100644 --- a/src/libserialize/serialize.rs +++ b/src/libserialize/serialize.rs @@ -593,50 +593,6 @@ impl Decodable for Arc { } } -// ___________________________________________________________________________ -// Helper routines - -pub trait EncoderHelpers: Encoder { - fn emit_from_vec(&mut self, v: &[T], f: F) - -> Result<(), Self::Error> - where F: FnMut(&mut Self, &T) -> Result<(), Self::Error>; -} - -impl EncoderHelpers for S { - fn emit_from_vec(&mut self, v: &[T], mut f: F) -> Result<(), S::Error> where - F: FnMut(&mut S, &T) -> Result<(), S::Error>, - { - self.emit_seq(v.len(), |this| { - for (i, e) in v.iter().enumerate() { - this.emit_seq_elt(i, |this| { - f(this, e) - })?; - } - Ok(()) - }) - } -} - -pub trait DecoderHelpers: Decoder { - fn read_to_vec(&mut self, f: F) - -> Result, Self::Error> where - F: FnMut(&mut Self) -> Result; -} - -impl DecoderHelpers for D { - fn read_to_vec(&mut self, mut f: F) -> Result, D::Error> where F: - FnMut(&mut D) -> Result, - { - self.read_seq(|this, len| { - let mut v = Vec::with_capacity(len); - for i in 0..len { - v.push(this.read_seq_elt(i, |this| f(this))?); - } - Ok(v) - }) - } -} - // ___________________________________________________________________________ // Specialization-based interface for multi-dispatch Encodable/Decodable. diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 40c8ba93bd5d9..70e614f9c9a91 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -27,7 +27,9 @@ use tokenstream::{TokenTree}; use std::fmt; use std::rc::Rc; -use serialize::{Encodable, Decodable, Encoder, Decoder}; +use std::u32; + +use serialize::{self, Encodable, Decodable, Encoder, Decoder}; /// A name is a part of an identifier, representing a string or gensym. It's /// the result of interning. @@ -298,17 +300,43 @@ pub struct ParenthesizedParameterData { pub output: Option>, } -pub type CrateNum = u32; +#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, RustcEncodable, Hash, Debug)] +pub struct NodeId(u32); + +impl NodeId { + pub fn new(x: usize) -> NodeId { + assert!(x < (u32::MAX as usize)); + NodeId(x as u32) + } + + pub fn from_u32(x: u32) -> NodeId { + NodeId(x) + } + + pub fn as_usize(&self) -> usize { + self.0 as usize + } + + pub fn as_u32(&self) -> u32 { + self.0 + } +} + +impl fmt::Display for NodeId { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(&self.0, f) + } +} -pub type NodeId = u32; +impl serialize::UseSpecializedDecodable for NodeId {} /// Node id used to represent the root of the crate. -pub const CRATE_NODE_ID: NodeId = 0; +pub const CRATE_NODE_ID: NodeId = NodeId(0); /// When parsing and doing expansions, we initially give all AST nodes this AST /// node value. Then later, in the renumber pass, we renumber them to have /// small, positive ids. -pub const DUMMY_NODE_ID: NodeId = !0; +pub const DUMMY_NODE_ID: NodeId = NodeId(!0); /// The AST represents all type param bounds as types. /// typeck::collect::compute_bounds matches these against diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index 81ee96459fd64..dc02c26039c15 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -895,7 +895,7 @@ pub fn find_repr_attrs(diagnostic: &Handler, attr: &Attribute) -> Vec "packed" => Some(ReprPacked), "simd" => Some(ReprSimd), _ => match int_type_of_word(word) { - Some(ity) => Some(ReprInt(item.span, ity)), + Some(ity) => Some(ReprInt(ity)), None => { // Not a word we recognize span_err!(diagnostic, item.span, E0552, @@ -939,7 +939,7 @@ fn int_type_of_word(s: &str) -> Option { #[derive(PartialEq, Debug, RustcEncodable, RustcDecodable, Copy, Clone)] pub enum ReprAttr { ReprAny, - ReprInt(Span, IntType), + ReprInt(IntType), ReprExtern, ReprPacked, ReprSimd, @@ -949,7 +949,7 @@ impl ReprAttr { pub fn is_ffi_safe(&self) -> bool { match *self { ReprAny => false, - ReprInt(_sp, ity) => ity.is_ffi_safe(), + ReprInt(ity) => ity.is_ffi_safe(), ReprExtern => true, ReprPacked => false, ReprSimd => true, diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 4e87d8ee9dda2..db0183a8b3a27 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -242,11 +242,11 @@ impl<'a, 'b> MacroExpander<'a, 'b> { while let Some(expansions) = expansions.pop() { for (mark, expansion) in expansions.into_iter().rev() { let expansion = expansion.fold_with(&mut placeholder_expander); - placeholder_expander.add(mark, expansion); + placeholder_expander.add(ast::NodeId::from_u32(mark), expansion); } } - placeholder_expander.remove(0) + placeholder_expander.remove(ast::NodeId::from_u32(0)) } fn collect_invocations(&mut self, expansion: Expansion) -> (Expansion, Vec) { @@ -424,7 +424,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { expansion_kind: expansion_kind, expansion_data: ExpansionData { mark: mark, ..self.cx.current_expansion.clone() }, }); - placeholder(expansion_kind, mark.as_u32()) + placeholder(expansion_kind, ast::NodeId::from_u32(mark.as_u32())) } fn collect_bang( diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 4a2c9aff2d2b4..118ceb17ab4a4 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -33,6 +33,7 @@ #![feature(unicode)] #![feature(question_mark)] #![feature(rustc_diagnostic_macros)] +#![feature(specialization)] extern crate serialize; extern crate term; diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index 339a6c477ccd5..e307925a6ed83 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -780,17 +780,17 @@ fn find_repr_type_name(diagnostic: &Handler, type_attrs: &[ast::Attribute]) -> & attr::ReprAny | attr::ReprPacked | attr::ReprSimd => continue, attr::ReprExtern => "i32", - attr::ReprInt(_, attr::SignedInt(ast::IntTy::Is)) => "isize", - attr::ReprInt(_, attr::SignedInt(ast::IntTy::I8)) => "i8", - attr::ReprInt(_, attr::SignedInt(ast::IntTy::I16)) => "i16", - attr::ReprInt(_, attr::SignedInt(ast::IntTy::I32)) => "i32", - attr::ReprInt(_, attr::SignedInt(ast::IntTy::I64)) => "i64", - - attr::ReprInt(_, attr::UnsignedInt(ast::UintTy::Us)) => "usize", - attr::ReprInt(_, attr::UnsignedInt(ast::UintTy::U8)) => "u8", - attr::ReprInt(_, attr::UnsignedInt(ast::UintTy::U16)) => "u16", - attr::ReprInt(_, attr::UnsignedInt(ast::UintTy::U32)) => "u32", - attr::ReprInt(_, attr::UnsignedInt(ast::UintTy::U64)) => "u64", + attr::ReprInt(attr::SignedInt(ast::IntTy::Is)) => "isize", + attr::ReprInt(attr::SignedInt(ast::IntTy::I8)) => "i8", + attr::ReprInt(attr::SignedInt(ast::IntTy::I16)) => "i16", + attr::ReprInt(attr::SignedInt(ast::IntTy::I32)) => "i32", + attr::ReprInt(attr::SignedInt(ast::IntTy::I64)) => "i64", + + attr::ReprInt(attr::UnsignedInt(ast::UintTy::Us)) => "usize", + attr::ReprInt(attr::UnsignedInt(ast::UintTy::U8)) => "u8", + attr::ReprInt(attr::UnsignedInt(ast::UintTy::U16)) => "u16", + attr::ReprInt(attr::UnsignedInt(ast::UintTy::U32)) => "u32", + attr::ReprInt(attr::UnsignedInt(ast::UintTy::U64)) => "u64", } } } diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index d835f8058fa0e..fb59f41110670 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -28,6 +28,7 @@ #![feature(rustc_private)] #![feature(staged_api)] #![feature(question_mark)] +#![feature(specialization)] use std::cell::{Cell, RefCell}; use std::ops::{Add, Sub}; @@ -151,21 +152,7 @@ impl Encodable for Span { } } -impl Decodable for Span { - fn decode(d: &mut D) -> Result { - d.read_struct("Span", 2, |d| { - let lo = d.read_struct_field("lo", 0, |d| { - BytePos::decode(d) - })?; - - let hi = d.read_struct_field("hi", 1, |d| { - BytePos::decode(d) - })?; - - Ok(mk_sp(lo, hi)) - }) - } -} +impl serialize::UseSpecializedDecodable for Span {} fn default_span_debug(span: Span, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Span {{ lo: {:?}, hi: {:?}, expn_id: {:?} }}", From 903ec52ba9172e38026fd6b833053e1a019fe68e Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Wed, 31 Aug 2016 14:08:22 +0300 Subject: [PATCH 12/39] rustc: replace uses of NodeId in Def, other than closures and labels. --- src/librustc/hir/def.rs | 25 ++--------- src/librustc/hir/lowering.rs | 4 +- src/librustc/middle/expr_use_visitor.rs | 5 ++- src/librustc/middle/liveness.rs | 9 ++-- src/librustc/middle/mem_categorization.rs | 6 ++- src/librustc/mir/repr.rs | 4 +- src/librustc/util/ppaux.rs | 3 +- src/librustc_const_eval/eval.rs | 3 +- src/librustc_metadata/astencode.rs | 3 +- src/librustc_mir/build/mod.rs | 5 ++- src/librustc_mir/hair/cx/expr.rs | 8 ++-- src/librustc_mir/hair/cx/pattern.rs | 3 +- src/librustc_resolve/lib.rs | 13 +++--- src/librustc_save_analysis/dump_visitor.rs | 3 +- src/librustc_typeck/astconv.rs | 21 +++------ src/librustc_typeck/check/_match.rs | 3 +- src/librustc_typeck/check/mod.rs | 3 +- src/librustc_typeck/check/upvar.rs | 52 +++++++++++----------- src/librustdoc/clean/mod.rs | 7 +-- 19 files changed, 83 insertions(+), 97 deletions(-) diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs index a270be4f1dfda..b4418ed424ea3 100644 --- a/src/librustc/hir/def.rs +++ b/src/librustc/hir/def.rs @@ -16,14 +16,13 @@ use hir; #[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub enum Def { Fn(DefId), - SelfTy(Option /* trait */, Option /* impl */), + SelfTy(Option /* trait */, Option /* impl */), Mod(DefId), ForeignMod(DefId), Static(DefId, bool /* is_mutbl */), Const(DefId), AssociatedConst(DefId), - Local(DefId, // def id of variable - ast::NodeId), // node id of variable + Local(DefId), Variant(DefId /* enum */, DefId /* variant */), Enum(DefId), TyAlias(DefId), @@ -32,7 +31,6 @@ pub enum Def { PrimTy(hir::PrimTy), TyParam(DefId), Upvar(DefId, // def id of closed over local - ast::NodeId, // node id of closed over local usize, // index in the freevars list of the closure ast::NodeId), // expr node that creates the closure @@ -101,30 +99,13 @@ pub struct Export { } impl Def { - pub fn var_id(&self) -> ast::NodeId { - match *self { - Def::Local(_, id) | - Def::Upvar(_, id, ..) => { - id - } - - Def::Fn(..) | Def::Mod(..) | Def::ForeignMod(..) | Def::Static(..) | - Def::Variant(..) | Def::Enum(..) | Def::TyAlias(..) | Def::AssociatedTy(..) | - Def::TyParam(..) | Def::Struct(..) | Def::Union(..) | Def::Trait(..) | - Def::Method(..) | Def::Const(..) | Def::AssociatedConst(..) | - Def::PrimTy(..) | Def::Label(..) | Def::SelfTy(..) | Def::Err => { - bug!("attempted .var_id() on invalid {:?}", self) - } - } - } - pub fn def_id(&self) -> DefId { match *self { Def::Fn(id) | Def::Mod(id) | Def::ForeignMod(id) | Def::Static(id, _) | Def::Variant(_, id) | Def::Enum(id) | Def::TyAlias(id) | Def::AssociatedTy(_, id) | Def::TyParam(id) | Def::Struct(id) | Def::Union(id) | Def::Trait(id) | Def::Method(id) | Def::Const(id) | Def::AssociatedConst(id) | - Def::Local(id, _) | Def::Upvar(id, ..) => { + Def::Local(id) | Def::Upvar(id, ..) => { id } diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 9f7400c983e5a..37b5eac3cceeb 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -1697,7 +1697,7 @@ impl<'a> LoweringContext<'a> { let def = { let defs = self.resolver.definitions(); - Def::Local(defs.local_def_id(binding), binding) + Def::Local(defs.local_def_id(binding)) }; self.resolver.record_resolution(expr.id, def); @@ -1850,7 +1850,7 @@ impl<'a> LoweringContext<'a> { let defs = self.resolver.definitions(); let def_path_data = DefPathData::Binding(name.as_str()); let def_index = defs.create_def_with_parent(parent_def, pat.id, def_path_data); - Def::Local(DefId::local(def_index), pat.id) + Def::Local(DefId::local(def_index)) }; self.resolver.record_resolution(pat.id, def); diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 9f05dde4e66f4..ec3fe3903179a 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -1029,7 +1029,8 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { self.tcx().with_freevars(closure_expr.id, |freevars| { for freevar in freevars { - let id_var = freevar.def.var_id(); + let def_id = freevar.def.def_id(); + let id_var = self.tcx().map.as_local_node_id(def_id).unwrap(); let upvar_id = ty::UpvarId { var_id: id_var, closure_expr_id: closure_expr.id }; let upvar_capture = self.mc.infcx.upvar_capture(upvar_id).unwrap(); @@ -1061,7 +1062,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { -> mc::McResult> { // Create the cmt for the variable being borrowed, from the // caller's perspective - let var_id = upvar_def.var_id(); + let var_id = self.tcx().map.as_local_node_id(upvar_def.def_id()).unwrap(); let var_ty = self.mc.infcx.node_ty(var_id)?; self.mc.cat_def(closure_id, closure_span, var_ty, upvar_def) } diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index b579c69cd05c0..db9dd82d492d3 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -465,7 +465,8 @@ fn visit_expr(ir: &mut IrMaps, expr: &Expr) { let mut call_caps = Vec::new(); ir.tcx.with_freevars(expr.id, |freevars| { for fv in freevars { - if let Def::Local(_, rv) = fv.def { + if let Def::Local(def_id) = fv.def { + let rv = ir.tcx.map.as_local_node_id(def_id).unwrap(); let fv_ln = ir.add_live_node(FreeVarNode(fv.span)); call_caps.push(CaptureInfo {ln: fv_ln, var_nid: rv}); @@ -1270,7 +1271,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { fn access_path(&mut self, expr: &Expr, succ: LiveNode, acc: u32) -> LiveNode { match self.ir.tcx.expect_def(expr.id) { - Def::Local(_, nid) => { + Def::Local(def_id) => { + let nid = self.ir.tcx.map.as_local_node_id(def_id).unwrap(); let ln = self.live_node(expr.id, expr.span); if acc != 0 { self.init_from_succ(ln, succ); @@ -1529,11 +1531,12 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { fn check_lvalue(&mut self, expr: &Expr) { match expr.node { hir::ExprPath(..) => { - if let Def::Local(_, nid) = self.ir.tcx.expect_def(expr.id) { + if let Def::Local(def_id) = self.ir.tcx.expect_def(expr.id) { // Assignment to an immutable variable or argument: only legal // if there is no later assignment. If this local is actually // mutable, then check for a reassignment to flag the mutability // as being used. + let nid = self.ir.tcx.map.as_local_node_id(def_id).unwrap(); let ln = self.live_node(expr.id, expr.span); let var = self.variable(nid, expr.span); self.warn_about_dead_assign(expr.span, expr.id, ln, var); diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index c419f96e82095..26cc6007ed07a 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -549,7 +549,8 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { })) } - Def::Upvar(_, var_id, _, fn_node_id) => { + Def::Upvar(def_id, _, fn_node_id) => { + let var_id = self.tcx().map.as_local_node_id(def_id).unwrap(); let ty = self.node_ty(fn_node_id)?; match ty.sty { ty::TyClosure(closure_id, _) => { @@ -585,7 +586,8 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { } } - Def::Local(_, vid) => { + Def::Local(def_id) => { + let vid = self.tcx().map.as_local_node_id(def_id).unwrap(); Ok(Rc::new(cmt_ { id: id, span: span, diff --git a/src/librustc/mir/repr.rs b/src/librustc/mir/repr.rs index 53b6ccdbd530a..1ffaf3c0ed5a2 100644 --- a/src/librustc/mir/repr.rs +++ b/src/librustc/mir/repr.rs @@ -1098,7 +1098,9 @@ impl<'tcx> Debug for Rvalue<'tcx> { tcx.with_freevars(node_id, |freevars| { for (freevar, lv) in freevars.iter().zip(lvs) { - let var_name = tcx.local_var_name_str(freevar.def.var_id()); + let def_id = freevar.def.def_id(); + let var_id = tcx.map.as_local_node_id(def_id).unwrap(); + let var_name = tcx.local_var_name_str(var_id); struct_fmt.field(&var_name, lv); } }); diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 3b84ff86ab9fb..1df0cf2d5cdf6 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -920,7 +920,8 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> { let mut sep = " "; tcx.with_freevars(node_id, |freevars| { for (freevar, upvar_ty) in freevars.iter().zip(substs.upvar_tys) { - let node_id = freevar.def.var_id(); + let def_id = freevar.def.def_id(); + let node_id = tcx.map.as_local_node_id(def_id).unwrap(); write!(f, "{}{}:{}", sep, diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index 4ced9d87f0a5a..ede13aa4dc8b2 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -824,7 +824,8 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, Def::Struct(..) => { ConstVal::Struct(e.id) } - Def::Local(_, id) => { + Def::Local(def_id) => { + let id = tcx.map.as_local_node_id(def_id).unwrap(); debug!("Def::Local({:?}): {:?}", id, fn_args); if let Some(val) = fn_args.and_then(|args| args.get(&id)) { val.clone() diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs index 397b33178dce8..2f845936a6c4e 100644 --- a/src/librustc_metadata/astencode.rs +++ b/src/librustc_metadata/astencode.rs @@ -167,7 +167,8 @@ fn encode_side_tables_for_id(ecx: &mut EncodeContext, id: ast::NodeId) { ecx.tag(c::tag_table_upvar_capture_map, |ecx| { ecx.id(id); - let var_id = freevar.def.var_id(); + let def_id = freevar.def.def_id(); + let var_id = tcx.map.as_local_node_id(def_id).unwrap(); let upvar_id = ty::UpvarId { var_id: var_id, closure_expr_id: id diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 59d6cf1185969..23591f05b8774 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -197,8 +197,9 @@ pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, // Gather the upvars of a closure, if any. let upvar_decls: Vec<_> = tcx.with_freevars(fn_id, |freevars| { freevars.iter().map(|fv| { + let var_id = tcx.map.as_local_node_id(fv.def.def_id()).unwrap(); let by_ref = tcx.upvar_capture(ty::UpvarId { - var_id: fv.def.var_id(), + var_id: var_id, closure_expr_id: fn_id }).map_or(false, |capture| match capture { ty::UpvarCapture::ByValue => false, @@ -208,7 +209,7 @@ pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, debug_name: keywords::Invalid.name(), by_ref: by_ref }; - if let Some(hir::map::NodeLocal(pat)) = tcx.map.find(fv.def.var_id()) { + if let Some(hir::map::NodeLocal(pat)) = tcx.map.find(var_id) { if let hir::PatKind::Binding(_, ref ident, _) = pat.node { decl.debug_name = ident.node; } diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 4518f8cb373fa..248690befac0e 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -729,13 +729,15 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, let temp_lifetime = cx.tcx.region_maps.temporary_scope(expr.id); match def { - Def::Local(_, node_id) => { + Def::Local(def_id) => { + let node_id = cx.tcx.map.as_local_node_id(def_id).unwrap(); ExprKind::VarRef { id: node_id, } } - Def::Upvar(_, id_var, index, closure_expr_id) => { + Def::Upvar(def_id, index, closure_expr_id) => { + let id_var = cx.tcx.map.as_local_node_id(def_id).unwrap(); debug!("convert_var(upvar({:?}, {:?}, {:?}))", id_var, index, closure_expr_id); let var_ty = cx.tcx.node_id_to_type(id_var); @@ -974,7 +976,7 @@ fn capture_freevar<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, freevar: &hir::Freevar, freevar_ty: Ty<'tcx>) -> ExprRef<'tcx> { - let id_var = freevar.def.var_id(); + let id_var = cx.tcx.map.as_local_node_id(freevar.def.def_id()).unwrap(); let upvar_id = ty::UpvarId { var_id: id_var, closure_expr_id: closure_expr.id, diff --git a/src/librustc_mir/hair/cx/pattern.rs b/src/librustc_mir/hair/cx/pattern.rs index 3639b165eb5ab..2c946b078a2f5 100644 --- a/src/librustc_mir/hair/cx/pattern.rs +++ b/src/librustc_mir/hair/cx/pattern.rs @@ -158,7 +158,8 @@ impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> { } PatKind::Binding(bm, ref ident, ref sub) => { - let id = self.cx.tcx.expect_def(pat.id).var_id(); + let def_id = self.cx.tcx.expect_def(pat.id).def_id(); + let id = self.cx.tcx.map.as_local_node_id(def_id).unwrap(); let var_ty = self.cx.tcx.node_id_to_type(pat.id); let region = match var_ty.sty { ty::TyRef(r, _) => Some(r), diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 659edb86be166..5e78ac7ca94c7 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1959,7 +1959,8 @@ impl<'a> Resolver<'a> { // Resolve the self type. this.visit_ty(self_type); - this.with_self_rib(Def::SelfTy(trait_id, Some(item_id)), |this| { + let item_def_id = this.definitions.local_def_id(item_id); + this.with_self_rib(Def::SelfTy(trait_id, Some(item_def_id)), |this| { this.with_current_self_type(self_type, |this| { for impl_item in impl_items { this.resolve_visibility(&impl_item.vis); @@ -2243,7 +2244,7 @@ impl<'a> Resolver<'a> { // must not add it if it's in the bindings map // because that breaks the assumptions later // passes make about or-patterns.) - let mut def = Def::Local(self.definitions.local_def_id(pat_id), pat_id); + let mut def = Def::Local(self.definitions.local_def_id(pat_id)); match bindings.get(&ident.node).cloned() { Some(id) if id == outer_pat_id => { // `Variant(a, a)`, error @@ -2559,7 +2560,7 @@ impl<'a> Resolver<'a> { Def::Upvar(..) => { span_bug!(span, "unexpected {:?} in bindings", def) } - Def::Local(_, node_id) => { + Def::Local(def_id) => { for rib in ribs { match rib.kind { NormalRibKind | ModuleRibKind(..) | MacroDefinition(..) => { @@ -2567,13 +2568,13 @@ impl<'a> Resolver<'a> { } ClosureRibKind(function_id) => { let prev_def = def; - let node_def_id = self.definitions.local_def_id(node_id); + let node_id = self.definitions.as_local_node_id(def_id).unwrap(); let seen = self.freevars_seen .entry(function_id) .or_insert_with(|| NodeMap()); if let Some(&index) = seen.get(&node_id) { - def = Def::Upvar(node_def_id, node_id, index, function_id); + def = Def::Upvar(def_id, index, function_id); continue; } let vec = self.freevars @@ -2585,7 +2586,7 @@ impl<'a> Resolver<'a> { span: span, }); - def = Def::Upvar(node_def_id, node_id, depth, function_id); + def = Def::Upvar(def_id, depth, function_id); seen.insert(node_id, depth); } ItemRibKind | MethodRibKind(_) => { diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 37b31eda5a35a..2cbc110c56af9 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -1456,7 +1456,8 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor for DumpVisitor<'l, 'tcx, 'll, D> // process collected paths for &(id, ref p, immut, ref_kind) in &collector.collected_paths { match self.tcx.expect_def(id) { - Def::Local(_, id) => { + Def::Local(def_id) => { + let id = self.tcx.map.as_local_node_id(def_id).unwrap(); let mut value = if immut == ast::Mutability::Immutable { self.span.snippet(p.span).to_string() } else { diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 334b7a5063a3a..675c863a3bf06 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1284,23 +1284,17 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { // Find the type of the associated item, and the trait where the associated // item is declared. let bound = match (&ty.sty, ty_path_def) { - (_, Def::SelfTy(Some(trait_did), Some(impl_id))) => { - // For Def::SelfTy() values inlined from another crate, the - // impl_id will be DUMMY_NODE_ID, which would cause problems - // here. But we should never run into an impl from another crate - // in this pass. - assert!(impl_id != ast::DUMMY_NODE_ID); - + (_, Def::SelfTy(Some(_), Some(impl_def_id))) => { // `Self` in an impl of a trait - we have a concrete self type and a // trait reference. - let trait_ref = tcx.impl_trait_ref(tcx.map.local_def_id(impl_id)).unwrap(); + let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap(); let trait_ref = if let Some(free_substs) = self.get_free_substs() { trait_ref.subst(tcx, free_substs) } else { trait_ref }; - if self.ensure_super_predicates(span, trait_did).is_err() { + if self.ensure_super_predicates(span, trait_ref.def_id).is_err() { return (tcx.types.err, Def::Err); } @@ -1504,16 +1498,11 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { tcx.types.err } } - Def::SelfTy(_, Some(impl_id)) => { + Def::SelfTy(_, Some(def_id)) => { // Self in impl (we know the concrete type). - // For Def::SelfTy() values inlined from another crate, the - // impl_id will be DUMMY_NODE_ID, which would cause problems - // here. But we should never run into an impl from another crate - // in this pass. - assert!(impl_id != ast::DUMMY_NODE_ID); - tcx.prohibit_type_params(base_segments); + let impl_id = tcx.map.as_local_node_id(def_id).unwrap(); let ty = tcx.node_id_to_type(impl_id); if let Some(free_substs) = self.get_free_substs() { ty.subst(tcx, free_substs) diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index dd3ac6ff2d457..de7ca479b0b66 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -134,7 +134,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // what the type of the binding `x` ought to be match tcx.expect_def(pat.id) { Def::Err => {} - Def::Local(_, var_id) => { + Def::Local(def_id) => { + let var_id = tcx.map.as_local_node_id(def_id).unwrap(); if var_id != pat.id { let vt = self.local_ty(pat.span, var_id); self.demand_eqtype(pat.span, vt, typ); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 01d7b1e54751c..8d9fd523a8f52 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4188,7 +4188,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.tcx.prohibit_type_params(&segments[..segments.len() - poly_segments]); match def { - Def::Local(_, nid) | Def::Upvar(_, nid, ..) => { + Def::Local(def_id) | Def::Upvar(def_id, ..) => { + let nid = self.tcx.map.as_local_node_id(def_id).unwrap(); let ty = self.local_ty(span, nid); let ty = self.normalize_associated_types_in(span, &ty); self.write_ty(node_id, ty); diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index f4a0df4611d33..aa221c33b5ddb 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -120,7 +120,8 @@ impl<'a, 'gcx, 'tcx> SeedBorrowKind<'a, 'gcx, 'tcx> { self.fcx.tcx.with_freevars(expr.id, |freevars| { for freevar in freevars { - let var_node_id = freevar.def.var_id(); + let def_id = freevar.def.def_id(); + let var_node_id = self.fcx.tcx.map.as_local_node_id(def_id).unwrap(); let upvar_id = ty::UpvarId { var_id: var_node_id, closure_expr_id: expr.id }; debug!("seed upvar_id {:?}", upvar_id); @@ -236,31 +237,30 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> { // implemented. let tcx = self.fcx.tcx; tcx.with_freevars(closure_id, |freevars| { - freevars.iter() - .map(|freevar| { - let freevar_node_id = freevar.def.var_id(); - let freevar_ty = self.fcx.node_ty(freevar_node_id); - let upvar_id = ty::UpvarId { - var_id: freevar_node_id, - closure_expr_id: closure_id - }; - let capture = self.fcx.upvar_capture(upvar_id).unwrap(); - - debug!("freevar_node_id={:?} freevar_ty={:?} capture={:?}", - freevar_node_id, freevar_ty, capture); - - match capture { - ty::UpvarCapture::ByValue => freevar_ty, - ty::UpvarCapture::ByRef(borrow) => - tcx.mk_ref(borrow.region, - ty::TypeAndMut { - ty: freevar_ty, - mutbl: borrow.kind.to_mutbl_lossy(), - }), - } - }) - .collect() - }) + freevars.iter().map(|freevar| { + let def_id = freevar.def.def_id(); + let var_id = tcx.map.as_local_node_id(def_id).unwrap(); + let freevar_ty = self.fcx.node_ty(var_id); + let upvar_id = ty::UpvarId { + var_id: var_id, + closure_expr_id: closure_id + }; + let capture = self.fcx.upvar_capture(upvar_id).unwrap(); + + debug!("var_id={:?} freevar_ty={:?} capture={:?}", + var_id, freevar_ty, capture); + + match capture { + ty::UpvarCapture::ByValue => freevar_ty, + ty::UpvarCapture::ByRef(borrow) => + tcx.mk_ref(borrow.region, + ty::TypeAndMut { + ty: freevar_ty, + mutbl: borrow.kind.to_mutbl_lossy(), + }), + } + }).collect() + }) } fn adjust_upvar_borrow_kind_for_consume(&mut self, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 7ee173019a516..3983c098f306f 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2790,11 +2790,8 @@ fn register_def(cx: &DocContext, def: Def) -> DefId { Def::Static(i, _) => (i, TypeStatic), Def::Variant(i, _) => (i, TypeEnum), Def::SelfTy(Some(def_id), _) => (def_id, TypeTrait), - Def::SelfTy(_, Some(impl_id)) => { - // For Def::SelfTy() values inlined from another crate, the - // impl_id will be DUMMY_NODE_ID, which would cause problems. - // But we should never run into an impl from another crate here. - return cx.map.local_def_id(impl_id) + Def::SelfTy(_, Some(impl_def_id)) => { + return impl_def_id } _ => return def.def_id() }; From ed593bed882e1ad6bc7ff6a3b3b6730176b5536b Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Thu, 1 Sep 2016 06:19:58 +0300 Subject: [PATCH 13/39] rustc_metadata: go back to not using the opaque format. --- src/librustc_metadata/astencode.rs | 222 ++++++++++++--------------- src/librustc_metadata/common.rs | 21 +-- src/librustc_metadata/decoder.rs | 96 ++++++------ src/librustc_metadata/encoder.rs | 18 +-- src/librustc_metadata/rbml/reader.rs | 5 - src/librustc_metadata/rbml/writer.rs | 6 +- 6 files changed, 165 insertions(+), 203 deletions(-) diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs index 2f845936a6c4e..ce15ec6a29d28 100644 --- a/src/librustc_metadata/astencode.rs +++ b/src/librustc_metadata/astencode.rs @@ -14,9 +14,7 @@ use rustc::hir::map as ast_map; use rustc::hir::intravisit::{Visitor, IdRangeComputingVisitor, IdRange}; -use common as c; -use cstore; - +use cstore::CrateMetadata; use decoder::DecodeContext; use encoder::EncodeContext; @@ -28,7 +26,6 @@ use rustc::ty::{self, TyCtxt}; use syntax::ast; -use rbml::reader; use rbml; use rustc_serialize::{Decodable, Encodable}; @@ -36,35 +33,31 @@ use rustc_serialize::{Decodable, Encodable}; // Top-level methods. pub fn encode_inlined_item(ecx: &mut EncodeContext, ii: InlinedItemRef) { - ecx.tag(c::tag_ast, |ecx| { - ecx.tag(c::tag_id_range, |ecx| { - let mut visitor = IdRangeComputingVisitor::new(); - match ii { - InlinedItemRef::Item(_, i) => visitor.visit_item(i), - InlinedItemRef::TraitItem(_, ti) => visitor.visit_trait_item(ti), - InlinedItemRef::ImplItem(_, ii) => visitor.visit_impl_item(ii) - } - visitor.result().encode(&mut ecx.opaque()).unwrap() - }); + ecx.tag(::common::tag_ast, |ecx| { + let mut visitor = IdRangeComputingVisitor::new(); + match ii { + InlinedItemRef::Item(_, i) => visitor.visit_item(i), + InlinedItemRef::TraitItem(_, ti) => visitor.visit_trait_item(ti), + InlinedItemRef::ImplItem(_, ii) => visitor.visit_impl_item(ii) + } + visitor.result().encode(ecx).unwrap(); - ecx.tag(c::tag_tree, |ecx| ii.encode(ecx).unwrap()); + ii.encode(ecx).unwrap(); - ecx.tag(c::tag_table, |ecx| { - let mut visitor = SideTableEncodingIdVisitor { - ecx: ecx - }; - match ii { - InlinedItemRef::Item(_, i) => visitor.visit_item(i), - InlinedItemRef::TraitItem(_, ti) => visitor.visit_trait_item(ti), - InlinedItemRef::ImplItem(_, ii) => visitor.visit_impl_item(ii) - } - }); + let mut visitor = SideTableEncodingIdVisitor { + ecx: ecx + }; + match ii { + InlinedItemRef::Item(_, i) => visitor.visit_item(i), + InlinedItemRef::TraitItem(_, ti) => visitor.visit_trait_item(ti), + InlinedItemRef::ImplItem(_, ii) => visitor.visit_impl_item(ii) + } }); } /// Decodes an item from its AST in the cdata's metadata and adds it to the /// ast-map. -pub fn decode_inlined_item<'a, 'tcx>(cdata: &cstore::CrateMetadata, +pub fn decode_inlined_item<'a, 'tcx>(cdata: &CrateMetadata, tcx: TyCtxt<'a, 'tcx, 'tcx>, parent_def_path: ast_map::DefPath, parent_did: DefId, @@ -72,16 +65,14 @@ pub fn decode_inlined_item<'a, 'tcx>(cdata: &cstore::CrateMetadata, orig_did: DefId) -> &'tcx InlinedItem { debug!("> Decoding inlined fn: {:?}", tcx.item_path_str(orig_did)); - let from_id_range = { - let decoder = &mut ast_doc.get(c::tag_id_range).opaque(); - IdRange { - min: ast::NodeId::from_u32(u32::decode(decoder).unwrap()), - max: ast::NodeId::from_u32(u32::decode(decoder).unwrap()) - } - }; - let mut dcx = DecodeContext::new(tcx, cdata, from_id_range, - ast_doc.get(c::tag_tree)); - let ii = InlinedItem::decode(&mut dcx).unwrap(); + let dcx = &mut ast_doc.decoder(); + dcx.tcx = Some(tcx); + dcx.cdata = Some(cdata); + dcx.from_id_range = IdRange::decode(dcx).unwrap(); + let cnt = dcx.from_id_range.max.as_usize() - dcx.from_id_range.min.as_usize(); + dcx.to_id_range.min = tcx.sess.reserve_node_ids(cnt); + dcx.to_id_range.max = ast::NodeId::new(dcx.to_id_range.min.as_usize() + cnt); + let ii = InlinedItem::decode(dcx).unwrap(); let ii = ast_map::map_decoded_item(&tcx.map, parent_def_path, @@ -97,7 +88,7 @@ pub fn decode_inlined_item<'a, 'tcx>(cdata: &cstore::CrateMetadata, let inlined_did = tcx.map.local_def_id(item_node_id); tcx.register_item_type(inlined_did, tcx.lookup_item_type(orig_did)); - decode_side_tables(&mut dcx, ast_doc); + decode_side_tables(dcx, ast_doc); ii } @@ -116,7 +107,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.end_tag().unwrap(); } - fn id(&mut self, id: ast::NodeId) { + fn entry(&mut self, table: Table, id: ast::NodeId) { + table.encode(self).unwrap(); id.encode(self).unwrap(); } } @@ -131,67 +123,67 @@ impl<'a, 'b, 'tcx, 'v> Visitor<'v> for SideTableEncodingIdVisitor<'a, 'b, 'tcx> } } +#[derive(RustcEncodable, RustcDecodable, Debug)] +enum Table { + Def, + NodeType, + ItemSubsts, + Freevars, + MethodMap, + Adjustment, + UpvarCaptureMap, + ConstQualif, + CastKind +} + fn encode_side_tables_for_id(ecx: &mut EncodeContext, id: ast::NodeId) { let tcx = ecx.tcx; debug!("Encoding side tables for id {}", id); if let Some(def) = tcx.expect_def_or_none(id) { - ecx.tag(c::tag_table_def, |ecx| { - ecx.id(id); - def.encode(ecx).unwrap(); - }) + ecx.entry(Table::Def, id); + def.encode(ecx).unwrap(); } if let Some(ty) = tcx.node_types().get(&id) { - ecx.tag(c::tag_table_node_type, |ecx| { - ecx.id(id); - ty.encode(ecx).unwrap(); - }) + ecx.entry(Table::NodeType, id); + ty.encode(ecx).unwrap(); } if let Some(item_substs) = tcx.tables.borrow().item_substs.get(&id) { - ecx.tag(c::tag_table_item_subst, |ecx| { - ecx.id(id); - item_substs.substs.encode(ecx).unwrap(); - }) + ecx.entry(Table::ItemSubsts, id); + item_substs.substs.encode(ecx).unwrap(); } if let Some(fv) = tcx.freevars.borrow().get(&id) { - ecx.tag(c::tag_table_freevars, |ecx| { - ecx.id(id); - fv.encode(ecx).unwrap(); - }); + ecx.entry(Table::Freevars, id); + fv.encode(ecx).unwrap(); for freevar in fv { - ecx.tag(c::tag_table_upvar_capture_map, |ecx| { - ecx.id(id); - - let def_id = freevar.def.def_id(); - let var_id = tcx.map.as_local_node_id(def_id).unwrap(); - let upvar_id = ty::UpvarId { - var_id: var_id, - closure_expr_id: id - }; - let upvar_capture = tcx.tables - .borrow() - .upvar_capture_map - .get(&upvar_id) - .unwrap() - .clone(); - var_id.encode(ecx).unwrap(); - upvar_capture.encode(ecx).unwrap(); - }) + ecx.entry(Table::UpvarCaptureMap, id); + let def_id = freevar.def.def_id(); + let var_id = tcx.map.as_local_node_id(def_id).unwrap(); + let upvar_id = ty::UpvarId { + var_id: var_id, + closure_expr_id: id + }; + let upvar_capture = tcx.tables + .borrow() + .upvar_capture_map + .get(&upvar_id) + .unwrap() + .clone(); + var_id.encode(ecx).unwrap(); + upvar_capture.encode(ecx).unwrap(); } } let method_call = ty::MethodCall::expr(id); if let Some(method) = tcx.tables.borrow().method_map.get(&method_call) { - ecx.tag(c::tag_table_method_map, |ecx| { - ecx.id(id); - method_call.autoderef.encode(ecx).unwrap(); - method.encode(ecx).unwrap(); - }) + ecx.entry(Table::MethodMap, id); + method_call.autoderef.encode(ecx).unwrap(); + method.encode(ecx).unwrap(); } if let Some(adjustment) = tcx.tables.borrow().adjustments.get(&id) { @@ -200,91 +192,79 @@ fn encode_side_tables_for_id(ecx: &mut EncodeContext, id: ast::NodeId) { for autoderef in 0..adj.autoderefs { let method_call = ty::MethodCall::autoderef(id, autoderef as u32); if let Some(method) = tcx.tables.borrow().method_map.get(&method_call) { - ecx.tag(c::tag_table_method_map, |ecx| { - ecx.id(id); - method_call.autoderef.encode(ecx).unwrap(); - method.encode(ecx).unwrap(); - }) + ecx.entry(Table::MethodMap, id); + method_call.autoderef.encode(ecx).unwrap(); + method.encode(ecx).unwrap(); } } } _ => {} } - ecx.tag(c::tag_table_adjustments, |ecx| { - ecx.id(id); - adjustment.encode(ecx).unwrap(); - }) + ecx.entry(Table::Adjustment, id); + adjustment.encode(ecx).unwrap(); } if let Some(cast_kind) = tcx.cast_kinds.borrow().get(&id) { - ecx.tag(c::tag_table_cast_kinds, |ecx| { - ecx.id(id); - cast_kind.encode(ecx).unwrap() - }) + ecx.entry(Table::CastKind, id); + cast_kind.encode(ecx).unwrap(); } if let Some(qualif) = tcx.const_qualif_map.borrow().get(&id) { - ecx.tag(c::tag_table_const_qualif, |ecx| { - ecx.id(id); - qualif.encode(ecx).unwrap() - }) + ecx.entry(Table::ConstQualif, id); + qualif.encode(ecx).unwrap(); } } -fn decode_side_tables<'a, 'tcx>(dcx: &mut DecodeContext<'a, 'tcx>, - ast_doc: rbml::Doc<'a>) { - for (tag, entry_doc) in reader::docs(ast_doc.get(c::tag_table)) { - dcx.rbml_r = reader::Decoder::new(entry_doc); +fn decode_side_tables(dcx: &mut DecodeContext, ast_doc: rbml::Doc) { + while dcx.position() < ast_doc.end { + let table = Decodable::decode(dcx).unwrap(); let id = Decodable::decode(dcx).unwrap(); - debug!("decode_side_tables: entry for id={}, tag=0x{:x}", id, tag); - match tag { - c::tag_table_def => { + debug!("decode_side_tables: entry for id={}, table={:?}", id, table); + match table { + Table::Def => { let def = Decodable::decode(dcx).unwrap(); - dcx.tcx.def_map.borrow_mut().insert(id, def::PathResolution::new(def)); + dcx.tcx().def_map.borrow_mut().insert(id, def::PathResolution::new(def)); } - c::tag_table_node_type => { + Table::NodeType => { let ty = Decodable::decode(dcx).unwrap(); - dcx.tcx.node_type_insert(id, ty); + dcx.tcx().node_type_insert(id, ty); } - c::tag_table_item_subst => { + Table::ItemSubsts => { let item_substs = Decodable::decode(dcx).unwrap(); - dcx.tcx.tables.borrow_mut().item_substs.insert(id, item_substs); + dcx.tcx().tables.borrow_mut().item_substs.insert(id, item_substs); } - c::tag_table_freevars => { + Table::Freevars => { let fv_info = Decodable::decode(dcx).unwrap(); - dcx.tcx.freevars.borrow_mut().insert(id, fv_info); + dcx.tcx().freevars.borrow_mut().insert(id, fv_info); } - c::tag_table_upvar_capture_map => { + Table::UpvarCaptureMap => { let upvar_id = ty::UpvarId { var_id: Decodable::decode(dcx).unwrap(), closure_expr_id: id }; let ub = Decodable::decode(dcx).unwrap(); - dcx.tcx.tables.borrow_mut().upvar_capture_map.insert(upvar_id, ub); + dcx.tcx().tables.borrow_mut().upvar_capture_map.insert(upvar_id, ub); } - c::tag_table_method_map => { + Table::MethodMap => { let method_call = ty::MethodCall { expr_id: id, autoderef: Decodable::decode(dcx).unwrap() }; let method = Decodable::decode(dcx).unwrap(); - dcx.tcx.tables.borrow_mut().method_map.insert(method_call, method); + dcx.tcx().tables.borrow_mut().method_map.insert(method_call, method); } - c::tag_table_adjustments => { + Table::Adjustment => { let adj = Decodable::decode(dcx).unwrap(); - dcx.tcx.tables.borrow_mut().adjustments.insert(id, adj); + dcx.tcx().tables.borrow_mut().adjustments.insert(id, adj); } - c::tag_table_cast_kinds => { + Table::CastKind => { let cast_kind = Decodable::decode(dcx).unwrap(); - dcx.tcx.cast_kinds.borrow_mut().insert(id, cast_kind); + dcx.tcx().cast_kinds.borrow_mut().insert(id, cast_kind); } - c::tag_table_const_qualif => { + Table::ConstQualif => { let qualif = Decodable::decode(dcx).unwrap(); - dcx.tcx.const_qualif_map.borrow_mut().insert(id, qualif); - } - _ => { - bug!("unknown tag found in side tables: 0x{:x}", tag); + dcx.tcx().const_qualif_map.borrow_mut().insert(id, qualif); } } } diff --git a/src/librustc_metadata/common.rs b/src/librustc_metadata/common.rs index c18b417466f94..512f4ca6584c6 100644 --- a/src/librustc_metadata/common.rs +++ b/src/librustc_metadata/common.rs @@ -97,28 +97,11 @@ pub const tag_items_data_item_reexport_name: usize = 0x48; // used to encode crate_ctxt side tables pub const tag_ast: usize = 0x50; -pub const tag_tree: usize = 0x51; +// GAP 0x51 pub const tag_mir: usize = 0x52; -pub const tag_table: usize = 0x53; - -pub const tag_id_range: usize = 0x54; - -// GAP 0x55 -pub const tag_table_def: usize = 0x56; -pub const tag_table_node_type: usize = 0x57; -pub const tag_table_item_subst: usize = 0x58; -pub const tag_table_freevars: usize = 0x59; -// GAP 0x5a, 0x5b, 0x5c, 0x5d, 0x5e -pub const tag_table_method_map: usize = 0x5f; -// GAP 0x60 -pub const tag_table_adjustments: usize = 0x61; -// GAP 0x62, 0x63, 0x64, 0x65 -pub const tag_table_upvar_capture_map: usize = 0x66; -// GAP 0x67, 0x68 -pub const tag_table_const_qualif: usize = 0x69; -pub const tag_table_cast_kinds: usize = 0x6a; +// GAP 0x53...0x6a pub const tag_item_trait_item_sort: usize = 0x70; diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 72e95804ce8e3..1bec365e472b1 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -48,6 +48,7 @@ use std::io; use std::ops::{Deref, DerefMut}; use std::rc::Rc; use std::str; +use std::u32; use rbml::reader; use rbml; @@ -59,48 +60,48 @@ use syntax::print::pprust; use syntax_pos::{self, Span, BytePos, NO_EXPANSION}; pub struct DecodeContext<'a, 'tcx: 'a> { - pub rbml_r: rbml::reader::Decoder<'a>, - pub tcx: TyCtxt<'a, 'tcx, 'tcx>, - pub cdata: &'a cstore::CrateMetadata, - from_id_range: IdRange, - to_id_range: IdRange, + rbml_r: rbml::reader::Decoder<'a>, + pub tcx: Option>, + pub cdata: Option<&'a cstore::CrateMetadata>, + pub from_id_range: IdRange, + pub to_id_range: IdRange, // Cache the last used filemap for translating spans as an optimization. last_filemap_index: usize, } -impl<'a, 'tcx> DecodeContext<'a, 'tcx> { - pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, - cdata: &'a cstore::CrateMetadata, - from_id_range: IdRange, - doc: rbml::Doc<'a>) - -> DecodeContext<'a, 'tcx> { - // Handle the case of an empty range: - let to_id_range = if from_id_range.empty() { - from_id_range - } else { - let cnt = from_id_range.max.as_usize() - from_id_range.min.as_usize(); - let to_id_min = tcx.sess.reserve_node_ids(cnt); - let to_id_max = NodeId::new(to_id_min.as_usize() + cnt); - IdRange { min: to_id_min, max: to_id_max } +impl<'doc> rbml::Doc<'doc> { + pub fn decoder<'tcx>(self) -> DecodeContext<'doc, 'tcx> { + let id_range = IdRange { + min: NodeId::from_u32(u32::MIN), + max: NodeId::from_u32(u32::MAX) }; - DecodeContext { - rbml_r: reader::Decoder::new(doc), - cdata: cdata, - tcx: tcx, - from_id_range: from_id_range, - to_id_range: to_id_range, + rbml_r: reader::Decoder::new(self), + cdata: None, + tcx: None, + from_id_range: id_range, + to_id_range: id_range, last_filemap_index: 0 } } +} + +impl<'a, 'tcx> DecodeContext<'a, 'tcx> { + pub fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> { + self.tcx.expect("missing TyCtxt in DecodeContext") + } + + pub fn cdata(&self) -> &'a cstore::CrateMetadata { + self.cdata.expect("missing CrateMetadata in DecodeContext") + } fn read_ty_encoded(&mut self, op: F) -> R where F: for<'x> FnOnce(&mut TyDecoder<'x,'tcx>) -> R { self.read_opaque(|this, doc| { Ok(op(&mut TyDecoder::with_doc( - this.tcx, this.cdata.cnum, doc, - &mut |d| translate_def_id(&this.cdata, d)))) + this.tcx(), this.cdata().cnum, doc, + &mut |d| translate_def_id(this.cdata(), d)))) }).unwrap() } } @@ -142,9 +143,9 @@ impl<'a, 'tcx> SpecializedDecoder for DecodeContext<'a, 'tcx> { fn specialized_decode(&mut self) -> Result { let cnum = CrateNum::from_u32(u32::decode(self)?); if cnum == LOCAL_CRATE { - Ok(self.cdata.cnum) + Ok(self.cdata().cnum) } else { - Ok(self.cdata.cnum_map.borrow()[cnum]) + Ok(self.cdata().cnum_map.borrow()[cnum]) } } } @@ -154,6 +155,12 @@ impl<'a, 'tcx> SpecializedDecoder for DecodeContext<'a, 'tcx> { let lo = BytePos::decode(self)?; let hi = BytePos::decode(self)?; + let tcx = if let Some(tcx) = self.tcx { + tcx + } else { + return Ok(syntax_pos::mk_sp(lo, hi)); + }; + let (lo, hi) = if lo > hi { // Currently macro expansion sometimes produces invalid Span values // where lo > hi. In order not to crash the compiler when trying to @@ -167,7 +174,7 @@ impl<'a, 'tcx> SpecializedDecoder for DecodeContext<'a, 'tcx> { (lo, hi) }; - let imported_filemaps = self.cdata.imported_filemaps(&self.tcx.sess.codemap()); + let imported_filemaps = self.cdata().imported_filemaps(&tcx.sess.codemap()); let filemap = { // Optimize for the case that most spans within a translated item // originate from the same filemap. @@ -224,7 +231,7 @@ impl<'a, 'tcx> SpecializedDecoder<&'tcx Substs<'tcx>> for DecodeContext<'a, 'tcx impl<'a, 'tcx> SpecializedDecoder<&'tcx ty::Region> for DecodeContext<'a, 'tcx> { fn specialized_decode(&mut self) -> Result<&'tcx ty::Region, Self::Error> { let r = ty::Region::decode(self)?; - Ok(self.tcx.mk_region(r)) + Ok(self.tcx().mk_region(r)) } } @@ -232,7 +239,7 @@ impl<'a, 'tcx> SpecializedDecoder> for DecodeContext<'a, fn specialized_decode(&mut self) -> Result, Self::Error> { Ok(ty::ClosureSubsts { func_substs: Decodable::decode(self)?, - upvar_tys: self.tcx.mk_type_list(Decodable::decode(self)?) + upvar_tys: self.tcx().mk_type_list(Decodable::decode(self)?) }) } } @@ -240,7 +247,7 @@ impl<'a, 'tcx> SpecializedDecoder> for DecodeContext<'a, impl<'a, 'tcx> SpecializedDecoder> for DecodeContext<'a, 'tcx> { fn specialized_decode(&mut self) -> Result, Self::Error> { let def_id = DefId::decode(self)?; - Ok(self.tcx.lookup_adt_def(def_id)) + Ok(self.tcx().lookup_adt_def(def_id)) } } @@ -739,14 +746,14 @@ pub fn get_type<'a, 'tcx>(cdata: Cmd, id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) pub fn get_stability(cdata: Cmd, id: DefIndex) -> Option { let item = cdata.lookup_item(id); reader::maybe_get_doc(item, tag_items_data_item_stability).map(|doc| { - Decodable::decode(&mut doc.opaque()).unwrap() + Decodable::decode(&mut doc.decoder()).unwrap() }) } pub fn get_deprecation(cdata: Cmd, id: DefIndex) -> Option { let item = cdata.lookup_item(id); reader::maybe_get_doc(item, tag_items_data_item_deprecation).map(|doc| { - Decodable::decode(&mut doc.opaque()).unwrap() + Decodable::decode(&mut doc.decoder()).unwrap() }) } @@ -764,7 +771,7 @@ pub fn get_parent_impl(cdata: Cmd, id: DefIndex) -> Option { pub fn get_repr_attrs(cdata: Cmd, id: DefIndex) -> Vec { let item = cdata.lookup_item(id); reader::maybe_get_doc(item, tag_items_data_item_repr).map_or(vec![], |doc| { - Decodable::decode(&mut doc.opaque()).unwrap() + Decodable::decode(&mut doc.decoder()).unwrap() }) } @@ -786,7 +793,7 @@ pub fn get_custom_coerce_unsized_kind( { let item_doc = cdata.lookup_item(id); reader::maybe_get_doc(item_doc, tag_impl_coerce_unsized_kind).map(|kind_doc| { - Decodable::decode(&mut kind_doc.opaque()).unwrap() + Decodable::decode(&mut kind_doc.decoder()).unwrap() }) } @@ -982,8 +989,9 @@ pub fn maybe_get_item_mir<'a, 'tcx>(cdata: Cmd, let item_doc = cdata.lookup_item(id); reader::maybe_get_doc(item_doc, tag_mir).map(|mir_doc| { - let id_range = IdRange { min: NodeId::new(0), max: NodeId::new(0) }; - let mut dcx = DecodeContext::new(tcx, cdata, id_range, mir_doc); + let mut dcx = mir_doc.decoder(); + dcx.tcx = Some(tcx); + dcx.cdata = Some(cdata); Decodable::decode(&mut dcx).unwrap() }) } @@ -1123,7 +1131,7 @@ pub fn get_trait_item_def_ids(cdata: Cmd, id: DefIndex) pub fn get_item_variances(cdata: Cmd, id: DefIndex) -> Vec { let item_doc = cdata.lookup_item(id); let variance_doc = reader::get_doc(item_doc, tag_item_variances); - Decodable::decode(&mut variance_doc.opaque()).unwrap() + Decodable::decode(&mut variance_doc.decoder()).unwrap() } pub fn get_provided_trait_methods<'a, 'tcx>(cdata: Cmd, @@ -1242,7 +1250,7 @@ pub fn get_struct_field_names(cdata: Cmd, id: DefIndex) -> Vec { fn get_attributes(md: rbml::Doc) -> Vec { reader::maybe_get_doc(md, tag_attributes).map_or(vec![], |attrs_doc| { - let mut attrs = Vec::::decode(&mut attrs_doc.opaque()).unwrap(); + let mut attrs = Vec::::decode(&mut attrs_doc.decoder()).unwrap(); // Need new unique IDs: old thread-local IDs won't map to new threads. for attr in attrs.iter_mut() { @@ -1647,14 +1655,14 @@ pub fn get_imported_filemaps(metadata: &[u8]) -> Vec { let cm_doc = reader::get_doc(crate_doc, tag_codemap); reader::tagged_docs(cm_doc, tag_codemap_filemap).map(|filemap_doc| { - Decodable::decode(&mut filemap_doc.opaque()).unwrap() + Decodable::decode(&mut filemap_doc.decoder()).unwrap() }).collect() } pub fn closure_kind(cdata: Cmd, closure_id: DefIndex) -> ty::ClosureKind { let closure_doc = cdata.lookup_item(closure_id); let closure_kind_doc = reader::get_doc(closure_doc, tag_items_closure_kind); - ty::ClosureKind::decode(&mut closure_kind_doc.opaque()).unwrap() + ty::ClosureKind::decode(&mut closure_kind_doc.decoder()).unwrap() } pub fn closure_ty<'a, 'tcx>(cdata: Cmd, closure_id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) @@ -1674,7 +1682,7 @@ pub fn def_key(cdata: Cmd, id: DefIndex) -> hir_map::DefKey { fn item_def_key(item_doc: rbml::Doc) -> hir_map::DefKey { match reader::maybe_get_doc(item_doc, tag_def_key) { Some(def_key_doc) => { - let simple_key = def_key::DefKey::decode(&mut def_key_doc.opaque()).unwrap(); + let simple_key = def_key::DefKey::decode(&mut def_key_doc.decoder()).unwrap(); let name = reader::maybe_get_doc(item_doc, tag_paths_data_name).map(|name| { token::intern(name.as_str()).as_str() }); diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index e493daab09103..9773823c77ded 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -108,7 +108,7 @@ fn encode_def_id(ecx: &mut EncodeContext, id: DefId) { fn encode_def_key(ecx: &mut EncodeContext, key: DefKey) { let simple_key = def_key::simplify_def_key(key); ecx.start_tag(tag_def_key); - simple_key.encode(&mut ecx.opaque()); + simple_key.encode(ecx); ecx.end_tag(); } @@ -146,7 +146,7 @@ pub fn def_to_string(_tcx: TyCtxt, did: DefId) -> String { fn encode_item_variances(ecx: &mut EncodeContext, id: NodeId) { let v = ecx.tcx.item_variances(ecx.tcx.map.local_def_id(id)); ecx.start_tag(tag_item_variances); - v.encode(&mut ecx.opaque()); + v.encode(ecx); ecx.end_tag(); } @@ -761,7 +761,7 @@ impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { attr)); } self.start_tag(tag_items_data_item_repr); - repr_attrs.encode(&mut self.opaque()); + repr_attrs.encode(self.ecx); self.end_tag(); } @@ -796,7 +796,7 @@ fn encode_inherent_implementations(ecx: &mut EncodeContext, fn encode_stability(ecx: &mut EncodeContext, stab_opt: Option<&attr::Stability>) { stab_opt.map(|stab| { ecx.start_tag(tag_items_data_item_stability); - stab.encode(&mut ecx.opaque()).unwrap(); + stab.encode(ecx).unwrap(); ecx.end_tag(); }); } @@ -804,7 +804,7 @@ fn encode_stability(ecx: &mut EncodeContext, stab_opt: Option<&attr::Stability>) fn encode_deprecation(ecx: &mut EncodeContext, depr_opt: Option) { depr_opt.map(|depr| { ecx.start_tag(tag_items_data_item_deprecation); - depr.encode(&mut ecx.opaque()).unwrap(); + depr.encode(ecx).unwrap(); ecx.end_tag(); }); } @@ -1043,7 +1043,7 @@ impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { { Some(&kind) => { self.start_tag(tag_impl_coerce_unsized_kind); - kind.encode(&mut self.opaque()); + kind.encode(self.ecx); self.end_tag(); } None => {} @@ -1361,7 +1361,7 @@ impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { self.end_tag(); self.start_tag(tag_items_closure_kind); - tcx.closure_kind(def_id).encode(&mut self.opaque()).unwrap(); + tcx.closure_kind(def_id).encode(self.ecx).unwrap(); self.end_tag(); assert!(self.mir_map.map.contains_key(&def_id)); @@ -1403,7 +1403,7 @@ fn encode_item_index(ecx: &mut EncodeContext, index: IndexData) { fn encode_attributes(ecx: &mut EncodeContext, attrs: &[ast::Attribute]) { ecx.start_tag(tag_attributes); - attrs.encode(&mut ecx.opaque()).unwrap(); + attrs.encode(ecx).unwrap(); ecx.end_tag(); } @@ -1538,7 +1538,7 @@ fn encode_codemap(ecx: &mut EncodeContext) { } ecx.start_tag(tag_codemap_filemap); - filemap.encode(&mut ecx.opaque()).unwrap(); + filemap.encode(ecx).unwrap(); ecx.end_tag(); } diff --git a/src/librustc_metadata/rbml/reader.rs b/src/librustc_metadata/rbml/reader.rs index 02acfef612a19..d66ca38e6244d 100644 --- a/src/librustc_metadata/rbml/reader.rs +++ b/src/librustc_metadata/rbml/reader.rs @@ -123,7 +123,6 @@ use std::str; use rustc_serialize as serialize; -use rbml::opaque; use rbml::Error; use rbml::Error::*; @@ -158,10 +157,6 @@ impl<'doc> Doc<'doc> { pub fn to_string(&self) -> String { self.as_str().to_string() } - - pub fn opaque(&self) -> opaque::Decoder<'doc> { - opaque::Decoder::new(self.data, self.start) - } } pub struct TaggedDoc<'a> { diff --git a/src/librustc_metadata/rbml/writer.rs b/src/librustc_metadata/rbml/writer.rs index db3a51187c60d..f22a9d1cd003e 100644 --- a/src/librustc_metadata/rbml/writer.rs +++ b/src/librustc_metadata/rbml/writer.rs @@ -254,15 +254,11 @@ impl Encoder { } } - pub fn opaque(&mut self) -> opaque::Encoder { - opaque::Encoder::new(&mut self.writer) - } - pub fn emit_opaque(&mut self, f: F) -> EncodeResult where F: FnOnce(&mut opaque::Encoder) -> EncodeResult { self.start_tag(EsOpaque as usize)?; - f(&mut self.opaque())?; + f(&mut opaque::Encoder::new(&mut self.writer))?; self.mark_stable_position(); self.end_tag() } From 02c4155d2cf0b17f526a126ad1f9dca944d9e85d Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Thu, 1 Sep 2016 10:21:12 +0300 Subject: [PATCH 14/39] rustc: remove hir::fold. --- src/librustc/hir/fold.rs | 1131 ------------------------ src/librustc/hir/mod.rs | 1 - src/librustc_const_eval/check_match.rs | 105 +-- src/librustdoc/clean/mod.rs | 120 ++- src/librustdoc/core.rs | 36 +- src/librustdoc/test.rs | 9 +- 6 files changed, 142 insertions(+), 1260 deletions(-) delete mode 100644 src/librustc/hir/fold.rs diff --git a/src/librustc/hir/fold.rs b/src/librustc/hir/fold.rs deleted file mode 100644 index 57b5599bd1d7f..0000000000000 --- a/src/librustc/hir/fold.rs +++ /dev/null @@ -1,1131 +0,0 @@ -// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! A Folder represents an HIR->HIR fold; it accepts a HIR piece, -//! and returns a piece of the same type. - -use hir::*; -use syntax::ast::{Name, NodeId, DUMMY_NODE_ID, Attribute, Attribute_}; -use syntax::ast::{NestedMetaItem, NestedMetaItemKind, MetaItem, MetaItemKind}; -use hir; -use syntax_pos::Span; -use syntax::codemap::{respan, Spanned}; -use syntax::ptr::P; -use syntax::parse::token::keywords; -use syntax::util::move_map::MoveMap; - -pub trait Folder : Sized { - // Any additions to this trait should happen in form - // of a call to a public `noop_*` function that only calls - // out to the folder again, not other `noop_*` functions. - // - // This is a necessary API workaround to the problem of not - // being able to call out to the super default method - // in an overridden default method. - - fn fold_crate(&mut self, c: Crate) -> Crate { - noop_fold_crate(c, self) - } - - fn fold_meta_items(&mut self, meta_items: HirVec>) -> HirVec> { - noop_fold_meta_items(meta_items, self) - } - - fn fold_meta_list_item(&mut self, list_item: NestedMetaItem) -> NestedMetaItem { - noop_fold_meta_list_item(list_item, self) - } - - fn fold_meta_item(&mut self, meta_item: P) -> P { - noop_fold_meta_item(meta_item, self) - } - - fn fold_view_path(&mut self, view_path: P) -> P { - noop_fold_view_path(view_path, self) - } - - fn fold_foreign_item(&mut self, ni: ForeignItem) -> ForeignItem { - noop_fold_foreign_item(ni, self) - } - - fn fold_item(&mut self, i: Item) -> Item { - noop_fold_item(i, self) - } - - fn fold_item_id(&mut self, i: ItemId) -> ItemId { - noop_fold_item_id(i, self) - } - - fn fold_struct_field(&mut self, sf: StructField) -> StructField { - noop_fold_struct_field(sf, self) - } - - fn fold_item_underscore(&mut self, i: Item_) -> Item_ { - noop_fold_item_underscore(i, self) - } - - fn fold_trait_item(&mut self, i: TraitItem) -> TraitItem { - noop_fold_trait_item(i, self) - } - - fn fold_impl_item(&mut self, i: ImplItem) -> ImplItem { - noop_fold_impl_item(i, self) - } - - fn fold_fn_decl(&mut self, d: P) -> P { - noop_fold_fn_decl(d, self) - } - - fn fold_block(&mut self, b: P) -> P { - noop_fold_block(b, self) - } - - fn fold_stmt(&mut self, s: Stmt) -> Stmt { - noop_fold_stmt(s, self) - } - - fn fold_arm(&mut self, a: Arm) -> Arm { - noop_fold_arm(a, self) - } - - fn fold_pat(&mut self, p: P) -> P { - noop_fold_pat(p, self) - } - - fn fold_decl(&mut self, d: P) -> P { - noop_fold_decl(d, self) - } - - fn fold_expr(&mut self, e: P) -> P { - e.map(|e| noop_fold_expr(e, self)) - } - - fn fold_ty(&mut self, t: P) -> P { - noop_fold_ty(t, self) - } - - fn fold_ty_binding(&mut self, t: TypeBinding) -> TypeBinding { - noop_fold_ty_binding(t, self) - } - - fn fold_mod(&mut self, m: Mod) -> Mod { - noop_fold_mod(m, self) - } - - fn fold_foreign_mod(&mut self, nm: ForeignMod) -> ForeignMod { - noop_fold_foreign_mod(nm, self) - } - - fn fold_variant(&mut self, v: Variant) -> Variant { - noop_fold_variant(v, self) - } - - fn fold_name(&mut self, n: Name) -> Name { - noop_fold_name(n, self) - } - - fn fold_usize(&mut self, i: usize) -> usize { - noop_fold_usize(i, self) - } - - fn fold_path(&mut self, p: Path) -> Path { - noop_fold_path(p, self) - } - - fn fold_path_parameters(&mut self, p: PathParameters) -> PathParameters { - noop_fold_path_parameters(p, self) - } - - fn fold_angle_bracketed_parameter_data(&mut self, - p: AngleBracketedParameterData) - -> AngleBracketedParameterData { - noop_fold_angle_bracketed_parameter_data(p, self) - } - - fn fold_parenthesized_parameter_data(&mut self, - p: ParenthesizedParameterData) - -> ParenthesizedParameterData { - noop_fold_parenthesized_parameter_data(p, self) - } - - fn fold_local(&mut self, l: P) -> P { - noop_fold_local(l, self) - } - - fn fold_lifetime(&mut self, l: Lifetime) -> Lifetime { - noop_fold_lifetime(l, self) - } - - fn fold_lifetime_def(&mut self, l: LifetimeDef) -> LifetimeDef { - noop_fold_lifetime_def(l, self) - } - - fn fold_attribute(&mut self, at: Attribute) -> Option { - noop_fold_attribute(at, self) - } - - fn fold_arg(&mut self, a: Arg) -> Arg { - noop_fold_arg(a, self) - } - - fn fold_generics(&mut self, generics: Generics) -> Generics { - noop_fold_generics(generics, self) - } - - fn fold_trait_ref(&mut self, p: TraitRef) -> TraitRef { - noop_fold_trait_ref(p, self) - } - - fn fold_poly_trait_ref(&mut self, p: PolyTraitRef) -> PolyTraitRef { - noop_fold_poly_trait_ref(p, self) - } - - fn fold_variant_data(&mut self, vdata: VariantData) -> VariantData { - noop_fold_variant_data(vdata, self) - } - - fn fold_lifetimes(&mut self, lts: HirVec) -> HirVec { - noop_fold_lifetimes(lts, self) - } - - fn fold_lifetime_defs(&mut self, lts: HirVec) -> HirVec { - noop_fold_lifetime_defs(lts, self) - } - - fn fold_ty_param(&mut self, tp: TyParam) -> TyParam { - noop_fold_ty_param(tp, self) - } - - fn fold_ty_params(&mut self, tps: HirVec) -> HirVec { - noop_fold_ty_params(tps, self) - } - - fn fold_opt_lifetime(&mut self, o_lt: Option) -> Option { - noop_fold_opt_lifetime(o_lt, self) - } - - fn fold_opt_bounds(&mut self, - b: Option) - -> Option { - noop_fold_opt_bounds(b, self) - } - - fn fold_bounds(&mut self, b: TyParamBounds) -> TyParamBounds { - noop_fold_bounds(b, self) - } - - fn fold_ty_param_bound(&mut self, tpb: TyParamBound) -> TyParamBound { - noop_fold_ty_param_bound(tpb, self) - } - - fn fold_mt(&mut self, mt: MutTy) -> MutTy { - noop_fold_mt(mt, self) - } - - fn fold_field(&mut self, field: Field) -> Field { - noop_fold_field(field, self) - } - - fn fold_where_clause(&mut self, where_clause: WhereClause) -> WhereClause { - noop_fold_where_clause(where_clause, self) - } - - fn fold_where_predicate(&mut self, where_predicate: WherePredicate) -> WherePredicate { - noop_fold_where_predicate(where_predicate, self) - } - - /// called for the `id` on each declaration - fn new_id(&mut self, i: NodeId) -> NodeId { - i - } - - /// called for ids that are references (e.g., ItemDef) - fn map_id(&mut self, i: NodeId) -> NodeId { - i - } - - fn new_span(&mut self, sp: Span) -> Span { - sp - } -} - -pub fn noop_fold_meta_items(meta_items: HirVec>, - fld: &mut T) - -> HirVec> { - meta_items.move_map(|x| fld.fold_meta_item(x)) -} - -pub fn noop_fold_view_path(view_path: P, fld: &mut T) -> P { - view_path.map(|Spanned { node, span }| { - Spanned { - node: match node { - ViewPathSimple(name, path) => { - ViewPathSimple(name, fld.fold_path(path)) - } - ViewPathGlob(path) => { - ViewPathGlob(fld.fold_path(path)) - } - ViewPathList(path, path_list_idents) => { - ViewPathList(fld.fold_path(path), - path_list_idents.move_map(|path_list_ident| { - Spanned { - node: PathListItem_ { - id: fld.new_id(path_list_ident.node.id), - name: path_list_ident.node.name, - rename: path_list_ident.node.rename, - }, - span: fld.new_span(path_list_ident.span), - } - })) - } - }, - span: fld.new_span(span), - } - }) -} - -pub fn fold_attrs(attrs: T, fld: &mut F) -> T - where T: Into> + From>, - F: Folder, -{ - attrs.into().move_flat_map(|x| fld.fold_attribute(x)).into() -} - -pub fn noop_fold_arm(Arm { attrs, pats, guard, body }: Arm, fld: &mut T) -> Arm { - Arm { - attrs: fold_attrs(attrs, fld), - pats: pats.move_map(|x| fld.fold_pat(x)), - guard: guard.map(|x| fld.fold_expr(x)), - body: fld.fold_expr(body), - } -} - -pub fn noop_fold_decl(d: P, fld: &mut T) -> P { - d.map(|Spanned { node, span }| { - match node { - DeclLocal(l) => Spanned { - node: DeclLocal(fld.fold_local(l)), - span: fld.new_span(span), - }, - DeclItem(it) => Spanned { - node: DeclItem(fld.fold_item_id(it)), - span: fld.new_span(span), - }, - } - }) -} - -pub fn noop_fold_ty_binding(b: TypeBinding, fld: &mut T) -> TypeBinding { - TypeBinding { - id: fld.new_id(b.id), - name: b.name, - ty: fld.fold_ty(b.ty), - span: fld.new_span(b.span), - } -} - -pub fn noop_fold_ty(t: P, fld: &mut T) -> P { - t.map(|Ty { id, node, span }| { - Ty { - id: fld.new_id(id), - node: match node { - TyInfer => node, - TyVec(ty) => TyVec(fld.fold_ty(ty)), - TyPtr(mt) => TyPtr(fld.fold_mt(mt)), - TyRptr(region, mt) => { - TyRptr(fld.fold_opt_lifetime(region), fld.fold_mt(mt)) - } - TyBareFn(f) => { - TyBareFn(f.map(|BareFnTy { lifetimes, unsafety, abi, decl }| { - BareFnTy { - lifetimes: fld.fold_lifetime_defs(lifetimes), - unsafety: unsafety, - abi: abi, - decl: fld.fold_fn_decl(decl), - } - })) - } - TyNever => node, - TyTup(tys) => TyTup(tys.move_map(|ty| fld.fold_ty(ty))), - TyPath(qself, path) => { - let qself = qself.map(|QSelf { ty, position }| { - QSelf { - ty: fld.fold_ty(ty), - position: position, - } - }); - TyPath(qself, fld.fold_path(path)) - } - TyObjectSum(ty, bounds) => { - TyObjectSum(fld.fold_ty(ty), fld.fold_bounds(bounds)) - } - TyFixedLengthVec(ty, e) => { - TyFixedLengthVec(fld.fold_ty(ty), fld.fold_expr(e)) - } - TyTypeof(expr) => { - TyTypeof(fld.fold_expr(expr)) - } - TyPolyTraitRef(bounds) => { - TyPolyTraitRef(bounds.move_map(|b| fld.fold_ty_param_bound(b))) - } - TyImplTrait(bounds) => { - TyImplTrait(bounds.move_map(|b| fld.fold_ty_param_bound(b))) - } - }, - span: fld.new_span(span), - } - }) -} - -pub fn noop_fold_foreign_mod(ForeignMod { abi, items }: ForeignMod, - fld: &mut T) - -> ForeignMod { - ForeignMod { - abi: abi, - items: items.move_map(|x| fld.fold_foreign_item(x)), - } -} - -pub fn noop_fold_variant(v: Variant, fld: &mut T) -> Variant { - Spanned { - node: Variant_ { - name: v.node.name, - attrs: fold_attrs(v.node.attrs, fld), - data: fld.fold_variant_data(v.node.data), - disr_expr: v.node.disr_expr.map(|e| fld.fold_expr(e)), - }, - span: fld.new_span(v.span), - } -} - -pub fn noop_fold_name(n: Name, _: &mut T) -> Name { - n -} - -pub fn noop_fold_usize(i: usize, _: &mut T) -> usize { - i -} - -pub fn noop_fold_path(Path { global, segments, span }: Path, fld: &mut T) -> Path { - Path { - global: global, - segments: segments.move_map(|PathSegment { name, parameters }| { - PathSegment { - name: fld.fold_name(name), - parameters: fld.fold_path_parameters(parameters), - } - }), - span: fld.new_span(span), - } -} - -pub fn noop_fold_path_parameters(path_parameters: PathParameters, - fld: &mut T) - -> PathParameters { - match path_parameters { - AngleBracketedParameters(data) => - AngleBracketedParameters(fld.fold_angle_bracketed_parameter_data(data)), - ParenthesizedParameters(data) => - ParenthesizedParameters(fld.fold_parenthesized_parameter_data(data)), - } -} - -pub fn noop_fold_angle_bracketed_parameter_data(data: AngleBracketedParameterData, - fld: &mut T) - -> AngleBracketedParameterData { - let AngleBracketedParameterData { lifetimes, types, bindings } = data; - AngleBracketedParameterData { - lifetimes: fld.fold_lifetimes(lifetimes), - types: types.move_map(|ty| fld.fold_ty(ty)), - bindings: bindings.move_map(|b| fld.fold_ty_binding(b)), - } -} - -pub fn noop_fold_parenthesized_parameter_data(data: ParenthesizedParameterData, - fld: &mut T) - -> ParenthesizedParameterData { - let ParenthesizedParameterData { inputs, output, span } = data; - ParenthesizedParameterData { - inputs: inputs.move_map(|ty| fld.fold_ty(ty)), - output: output.map(|ty| fld.fold_ty(ty)), - span: fld.new_span(span), - } -} - -pub fn noop_fold_local(l: P, fld: &mut T) -> P { - l.map(|Local { id, pat, ty, init, span, attrs }| { - Local { - id: fld.new_id(id), - ty: ty.map(|t| fld.fold_ty(t)), - pat: fld.fold_pat(pat), - init: init.map(|e| fld.fold_expr(e)), - span: fld.new_span(span), - attrs: fold_attrs(attrs, fld), - } - }) -} - -pub fn noop_fold_attribute(at: Attribute, fld: &mut T) -> Option { - let Spanned {node: Attribute_ {id, style, value, is_sugared_doc}, span} = at; - Some(Spanned { - node: Attribute_ { - id: id, - style: style, - value: fld.fold_meta_item(value), - is_sugared_doc: is_sugared_doc, - }, - span: fld.new_span(span), - }) -} - -pub fn noop_fold_meta_list_item(li: NestedMetaItem, fld: &mut T) - -> NestedMetaItem { - Spanned { - node: match li.node { - NestedMetaItemKind::MetaItem(mi) => { - NestedMetaItemKind::MetaItem(fld.fold_meta_item(mi)) - }, - NestedMetaItemKind::Literal(lit) => NestedMetaItemKind::Literal(lit) - }, - span: fld.new_span(li.span) - } -} - -pub fn noop_fold_meta_item(mi: P, fld: &mut T) -> P { - mi.map(|Spanned { node, span }| { - Spanned { - node: match node { - MetaItemKind::Word(id) => MetaItemKind::Word(id), - MetaItemKind::List(id, mis) => { - MetaItemKind::List(id, mis.move_map(|e| fld.fold_meta_list_item(e))) - } - MetaItemKind::NameValue(id, s) => MetaItemKind::NameValue(id, s), - }, - span: fld.new_span(span), - } - }) -} - -pub fn noop_fold_arg(Arg { id, pat, ty }: Arg, fld: &mut T) -> Arg { - Arg { - id: fld.new_id(id), - pat: fld.fold_pat(pat), - ty: fld.fold_ty(ty), - } -} - -pub fn noop_fold_fn_decl(decl: P, fld: &mut T) -> P { - decl.map(|FnDecl { inputs, output, variadic }| { - FnDecl { - inputs: inputs.move_map(|x| fld.fold_arg(x)), - output: match output { - Return(ty) => Return(fld.fold_ty(ty)), - DefaultReturn(span) => DefaultReturn(span), - }, - variadic: variadic, - } - }) -} - -pub fn noop_fold_ty_param_bound(tpb: TyParamBound, fld: &mut T) -> TyParamBound - where T: Folder -{ - match tpb { - TraitTyParamBound(ty, modifier) => TraitTyParamBound(fld.fold_poly_trait_ref(ty), modifier), - RegionTyParamBound(lifetime) => RegionTyParamBound(fld.fold_lifetime(lifetime)), - } -} - -pub fn noop_fold_ty_param(tp: TyParam, fld: &mut T) -> TyParam { - let TyParam {id, name, bounds, default, span} = tp; - TyParam { - id: fld.new_id(id), - name: name, - bounds: fld.fold_bounds(bounds), - default: default.map(|x| fld.fold_ty(x)), - span: span, - } -} - -pub fn noop_fold_ty_params(tps: HirVec, - fld: &mut T) - -> HirVec { - tps.move_map(|tp| fld.fold_ty_param(tp)) -} - -pub fn noop_fold_lifetime(l: Lifetime, fld: &mut T) -> Lifetime { - Lifetime { - id: fld.new_id(l.id), - name: l.name, - span: fld.new_span(l.span), - } -} - -pub fn noop_fold_lifetime_def(l: LifetimeDef, fld: &mut T) -> LifetimeDef { - LifetimeDef { - lifetime: fld.fold_lifetime(l.lifetime), - bounds: fld.fold_lifetimes(l.bounds), - } -} - -pub fn noop_fold_lifetimes(lts: HirVec, fld: &mut T) -> HirVec { - lts.move_map(|l| fld.fold_lifetime(l)) -} - -pub fn noop_fold_lifetime_defs(lts: HirVec, - fld: &mut T) - -> HirVec { - lts.move_map(|l| fld.fold_lifetime_def(l)) -} - -pub fn noop_fold_opt_lifetime(o_lt: Option, fld: &mut T) -> Option { - o_lt.map(|lt| fld.fold_lifetime(lt)) -} - -pub fn noop_fold_generics(Generics {ty_params, lifetimes, where_clause, span}: Generics, - fld: &mut T) - -> Generics { - Generics { - ty_params: fld.fold_ty_params(ty_params), - lifetimes: fld.fold_lifetime_defs(lifetimes), - where_clause: fld.fold_where_clause(where_clause), - span: fld.new_span(span), - } -} - -pub fn noop_fold_where_clause(WhereClause { id, predicates }: WhereClause, - fld: &mut T) - -> WhereClause { - WhereClause { - id: fld.new_id(id), - predicates: predicates.move_map(|predicate| fld.fold_where_predicate(predicate)), - } -} - -pub fn noop_fold_where_predicate(pred: WherePredicate, fld: &mut T) -> WherePredicate { - match pred { - hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate{bound_lifetimes, - bounded_ty, - bounds, - span}) => { - hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate { - bound_lifetimes: fld.fold_lifetime_defs(bound_lifetimes), - bounded_ty: fld.fold_ty(bounded_ty), - bounds: bounds.move_map(|x| fld.fold_ty_param_bound(x)), - span: fld.new_span(span), - }) - } - hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate{lifetime, - bounds, - span}) => { - hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate { - span: fld.new_span(span), - lifetime: fld.fold_lifetime(lifetime), - bounds: bounds.move_map(|bound| fld.fold_lifetime(bound)), - }) - } - hir::WherePredicate::EqPredicate(hir::WhereEqPredicate{id, - path, - ty, - span}) => { - hir::WherePredicate::EqPredicate(hir::WhereEqPredicate { - id: fld.new_id(id), - path: fld.fold_path(path), - ty: fld.fold_ty(ty), - span: fld.new_span(span), - }) - } - } -} - -pub fn noop_fold_variant_data(vdata: VariantData, fld: &mut T) -> VariantData { - match vdata { - VariantData::Struct(fields, id) => { - VariantData::Struct(fields.move_map(|f| fld.fold_struct_field(f)), - fld.new_id(id)) - } - VariantData::Tuple(fields, id) => { - VariantData::Tuple(fields.move_map(|f| fld.fold_struct_field(f)), - fld.new_id(id)) - } - VariantData::Unit(id) => VariantData::Unit(fld.new_id(id)), - } -} - -pub fn noop_fold_trait_ref(p: TraitRef, fld: &mut T) -> TraitRef { - let id = fld.new_id(p.ref_id); - let TraitRef { - path, - ref_id: _, - } = p; - hir::TraitRef { - path: fld.fold_path(path), - ref_id: id, - } -} - -pub fn noop_fold_poly_trait_ref(p: PolyTraitRef, fld: &mut T) -> PolyTraitRef { - hir::PolyTraitRef { - bound_lifetimes: fld.fold_lifetime_defs(p.bound_lifetimes), - trait_ref: fld.fold_trait_ref(p.trait_ref), - span: fld.new_span(p.span), - } -} - -pub fn noop_fold_struct_field(f: StructField, fld: &mut T) -> StructField { - StructField { - span: fld.new_span(f.span), - id: fld.new_id(f.id), - name: f.name, - vis: f.vis, - ty: fld.fold_ty(f.ty), - attrs: fold_attrs(f.attrs, fld), - } -} - -pub fn noop_fold_field(Field { name, expr, span }: Field, folder: &mut T) -> Field { - Field { - name: respan(folder.new_span(name.span), folder.fold_name(name.node)), - expr: folder.fold_expr(expr), - span: folder.new_span(span), - } -} - -pub fn noop_fold_mt(MutTy { ty, mutbl }: MutTy, folder: &mut T) -> MutTy { - MutTy { - ty: folder.fold_ty(ty), - mutbl: mutbl, - } -} - -pub fn noop_fold_opt_bounds(b: Option, - folder: &mut T) - -> Option { - b.map(|bounds| folder.fold_bounds(bounds)) -} - -fn noop_fold_bounds(bounds: TyParamBounds, folder: &mut T) -> TyParamBounds { - bounds.move_map(|bound| folder.fold_ty_param_bound(bound)) -} - -pub fn noop_fold_block(b: P, folder: &mut T) -> P { - b.map(|Block { id, stmts, expr, rules, span }| { - Block { - id: folder.new_id(id), - stmts: stmts.move_map(|s| folder.fold_stmt(s)), - expr: expr.map(|x| folder.fold_expr(x)), - rules: rules, - span: folder.new_span(span), - } - }) -} - -pub fn noop_fold_item_underscore(i: Item_, folder: &mut T) -> Item_ { - match i { - ItemExternCrate(string) => ItemExternCrate(string), - ItemUse(view_path) => { - ItemUse(folder.fold_view_path(view_path)) - } - ItemStatic(t, m, e) => { - ItemStatic(folder.fold_ty(t), m, folder.fold_expr(e)) - } - ItemConst(t, e) => { - ItemConst(folder.fold_ty(t), folder.fold_expr(e)) - } - ItemFn(decl, unsafety, constness, abi, generics, body) => { - ItemFn(folder.fold_fn_decl(decl), - unsafety, - constness, - abi, - folder.fold_generics(generics), - folder.fold_block(body)) - } - ItemMod(m) => ItemMod(folder.fold_mod(m)), - ItemForeignMod(nm) => ItemForeignMod(folder.fold_foreign_mod(nm)), - ItemTy(t, generics) => { - ItemTy(folder.fold_ty(t), folder.fold_generics(generics)) - } - ItemEnum(enum_definition, generics) => { - ItemEnum(hir::EnumDef { - variants: enum_definition.variants.move_map(|x| folder.fold_variant(x)), - }, - folder.fold_generics(generics)) - } - ItemStruct(struct_def, generics) => { - let struct_def = folder.fold_variant_data(struct_def); - ItemStruct(struct_def, folder.fold_generics(generics)) - } - ItemUnion(struct_def, generics) => { - let struct_def = folder.fold_variant_data(struct_def); - ItemUnion(struct_def, folder.fold_generics(generics)) - } - ItemDefaultImpl(unsafety, ref trait_ref) => { - ItemDefaultImpl(unsafety, folder.fold_trait_ref((*trait_ref).clone())) - } - ItemImpl(unsafety, polarity, generics, ifce, ty, impl_items) => { - let new_impl_items = impl_items - .move_map(|item| folder.fold_impl_item(item)); - let ifce = match ifce { - None => None, - Some(ref trait_ref) => { - Some(folder.fold_trait_ref((*trait_ref).clone())) - } - }; - ItemImpl(unsafety, - polarity, - folder.fold_generics(generics), - ifce, - folder.fold_ty(ty), - new_impl_items) - } - ItemTrait(unsafety, generics, bounds, items) => { - let bounds = folder.fold_bounds(bounds); - let items = items.move_map(|item| folder.fold_trait_item(item)); - ItemTrait(unsafety, folder.fold_generics(generics), bounds, items) - } - } -} - -pub fn noop_fold_trait_item(i: TraitItem, - folder: &mut T) - -> TraitItem { - TraitItem { - id: folder.new_id(i.id), - name: folder.fold_name(i.name), - attrs: fold_attrs(i.attrs, folder), - node: match i.node { - ConstTraitItem(ty, default) => { - ConstTraitItem(folder.fold_ty(ty), default.map(|x| folder.fold_expr(x))) - } - MethodTraitItem(sig, body) => { - MethodTraitItem(noop_fold_method_sig(sig, folder), - body.map(|x| folder.fold_block(x))) - } - TypeTraitItem(bounds, default) => { - TypeTraitItem(folder.fold_bounds(bounds), - default.map(|x| folder.fold_ty(x))) - } - }, - span: folder.new_span(i.span), - } -} - -pub fn noop_fold_impl_item(i: ImplItem, folder: &mut T) -> ImplItem { - ImplItem { - id: folder.new_id(i.id), - name: folder.fold_name(i.name), - attrs: fold_attrs(i.attrs, folder), - vis: i.vis, - defaultness: i.defaultness, - node: match i.node { - ImplItemKind::Const(ty, expr) => { - ImplItemKind::Const(folder.fold_ty(ty), folder.fold_expr(expr)) - } - ImplItemKind::Method(sig, body) => { - ImplItemKind::Method(noop_fold_method_sig(sig, folder), folder.fold_block(body)) - } - ImplItemKind::Type(ty) => ImplItemKind::Type(folder.fold_ty(ty)), - }, - span: folder.new_span(i.span), - } -} - -pub fn noop_fold_mod(Mod { inner, item_ids }: Mod, folder: &mut T) -> Mod { - Mod { - inner: folder.new_span(inner), - item_ids: item_ids.move_map(|x| folder.fold_item_id(x)), - } -} - -pub fn noop_fold_crate(Crate { module, attrs, config, span, - exported_macros, items }: Crate, - folder: &mut T) - -> Crate { - let config = folder.fold_meta_items(config); - - let crate_mod = folder.fold_item(hir::Item { - name: keywords::Invalid.name(), - attrs: attrs, - id: DUMMY_NODE_ID, - vis: hir::Public, - span: span, - node: hir::ItemMod(module), - }); - - let (module, attrs, span) = match crate_mod { - hir::Item { attrs, span, node, .. } => { - match node { - hir::ItemMod(m) => (m, attrs, span), - _ => panic!("fold converted a module to not a module"), - } - } - }; - - let items = items.into_iter() - .map(|(id, item)| (id, folder.fold_item(item))) - .collect(); - - Crate { - module: module, - attrs: attrs, - config: config, - span: span, - exported_macros: exported_macros, - items: items, - } -} - -pub fn noop_fold_item_id(i: ItemId, folder: &mut T) -> ItemId { - let id = folder.map_id(i.id); - ItemId { id: id } -} - -// fold one item into one item -pub fn noop_fold_item(item: Item, folder: &mut T) -> Item { - let Item { id, name, attrs, node, vis, span } = item; - let id = folder.new_id(id); - let node = folder.fold_item_underscore(node); - - Item { - id: id, - name: folder.fold_name(name), - attrs: fold_attrs(attrs, folder), - node: node, - vis: vis, - span: folder.new_span(span), - } -} - -pub fn noop_fold_foreign_item(ni: ForeignItem, folder: &mut T) -> ForeignItem { - ForeignItem { - id: folder.new_id(ni.id), - name: folder.fold_name(ni.name), - attrs: fold_attrs(ni.attrs, folder), - node: match ni.node { - ForeignItemFn(fdec, generics) => { - ForeignItemFn(folder.fold_fn_decl(fdec), folder.fold_generics(generics)) - } - ForeignItemStatic(t, m) => { - ForeignItemStatic(folder.fold_ty(t), m) - } - }, - vis: ni.vis, - span: folder.new_span(ni.span), - } -} - -pub fn noop_fold_method_sig(sig: MethodSig, folder: &mut T) -> MethodSig { - MethodSig { - generics: folder.fold_generics(sig.generics), - abi: sig.abi, - unsafety: sig.unsafety, - constness: sig.constness, - decl: folder.fold_fn_decl(sig.decl), - } -} - -pub fn noop_fold_pat(p: P, folder: &mut T) -> P { - p.map(|Pat { id, node, span }| { - Pat { - id: folder.new_id(id), - node: match node { - PatKind::Wild => PatKind::Wild, - PatKind::Binding(binding_mode, pth1, sub) => { - PatKind::Binding(binding_mode, - Spanned { - span: folder.new_span(pth1.span), - node: folder.fold_name(pth1.node), - }, - sub.map(|x| folder.fold_pat(x))) - } - PatKind::Lit(e) => PatKind::Lit(folder.fold_expr(e)), - PatKind::TupleStruct(pth, pats, ddpos) => { - PatKind::TupleStruct(folder.fold_path(pth), - pats.move_map(|x| folder.fold_pat(x)), ddpos) - } - PatKind::Path(opt_qself, pth) => { - let opt_qself = opt_qself.map(|qself| { - QSelf { ty: folder.fold_ty(qself.ty), position: qself.position } - }); - PatKind::Path(opt_qself, folder.fold_path(pth)) - } - PatKind::Struct(pth, fields, etc) => { - let pth = folder.fold_path(pth); - let fs = fields.move_map(|f| { - Spanned { - span: folder.new_span(f.span), - node: hir::FieldPat { - name: f.node.name, - pat: folder.fold_pat(f.node.pat), - is_shorthand: f.node.is_shorthand, - }, - } - }); - PatKind::Struct(pth, fs, etc) - } - PatKind::Tuple(elts, ddpos) => { - PatKind::Tuple(elts.move_map(|x| folder.fold_pat(x)), ddpos) - } - PatKind::Box(inner) => PatKind::Box(folder.fold_pat(inner)), - PatKind::Ref(inner, mutbl) => PatKind::Ref(folder.fold_pat(inner), mutbl), - PatKind::Range(e1, e2) => { - PatKind::Range(folder.fold_expr(e1), folder.fold_expr(e2)) - } - PatKind::Vec(before, slice, after) => { - PatKind::Vec(before.move_map(|x| folder.fold_pat(x)), - slice.map(|x| folder.fold_pat(x)), - after.move_map(|x| folder.fold_pat(x))) - } - }, - span: folder.new_span(span), - } - }) -} - -pub fn noop_fold_expr(Expr { id, node, span, attrs }: Expr, folder: &mut T) -> Expr { - Expr { - id: folder.new_id(id), - node: match node { - ExprBox(e) => { - ExprBox(folder.fold_expr(e)) - } - ExprVec(exprs) => { - ExprVec(exprs.move_map(|x| folder.fold_expr(x))) - } - ExprRepeat(expr, count) => { - ExprRepeat(folder.fold_expr(expr), folder.fold_expr(count)) - } - ExprTup(elts) => ExprTup(elts.move_map(|x| folder.fold_expr(x))), - ExprCall(f, args) => { - ExprCall(folder.fold_expr(f), args.move_map(|x| folder.fold_expr(x))) - } - ExprMethodCall(name, tps, args) => { - ExprMethodCall(respan(folder.new_span(name.span), folder.fold_name(name.node)), - tps.move_map(|x| folder.fold_ty(x)), - args.move_map(|x| folder.fold_expr(x))) - } - ExprBinary(binop, lhs, rhs) => { - ExprBinary(binop, folder.fold_expr(lhs), folder.fold_expr(rhs)) - } - ExprUnary(binop, ohs) => { - ExprUnary(binop, folder.fold_expr(ohs)) - } - ExprLit(l) => ExprLit(l), - ExprCast(expr, ty) => { - ExprCast(folder.fold_expr(expr), folder.fold_ty(ty)) - } - ExprType(expr, ty) => { - ExprType(folder.fold_expr(expr), folder.fold_ty(ty)) - } - ExprAddrOf(m, ohs) => ExprAddrOf(m, folder.fold_expr(ohs)), - ExprIf(cond, tr, fl) => { - ExprIf(folder.fold_expr(cond), - folder.fold_block(tr), - fl.map(|x| folder.fold_expr(x))) - } - ExprWhile(cond, body, opt_name) => { - ExprWhile(folder.fold_expr(cond), - folder.fold_block(body), - opt_name.map(|label| { - respan(folder.new_span(label.span), folder.fold_name(label.node)) - })) - } - ExprLoop(body, opt_name) => { - ExprLoop(folder.fold_block(body), - opt_name.map(|label| { - respan(folder.new_span(label.span), folder.fold_name(label.node)) - })) - } - ExprMatch(expr, arms, source) => { - ExprMatch(folder.fold_expr(expr), - arms.move_map(|x| folder.fold_arm(x)), - source) - } - ExprClosure(capture_clause, decl, body, fn_decl_span) => { - ExprClosure(capture_clause, - folder.fold_fn_decl(decl), - folder.fold_block(body), - folder.new_span(fn_decl_span)) - } - ExprBlock(blk) => ExprBlock(folder.fold_block(blk)), - ExprAssign(el, er) => { - ExprAssign(folder.fold_expr(el), folder.fold_expr(er)) - } - ExprAssignOp(op, el, er) => { - ExprAssignOp(op, folder.fold_expr(el), folder.fold_expr(er)) - } - ExprField(el, name) => { - ExprField(folder.fold_expr(el), - respan(folder.new_span(name.span), folder.fold_name(name.node))) - } - ExprTupField(el, index) => { - ExprTupField(folder.fold_expr(el), - respan(folder.new_span(index.span), folder.fold_usize(index.node))) - } - ExprIndex(el, er) => { - ExprIndex(folder.fold_expr(el), folder.fold_expr(er)) - } - ExprPath(qself, path) => { - let qself = qself.map(|QSelf { ty, position }| { - QSelf { - ty: folder.fold_ty(ty), - position: position, - } - }); - ExprPath(qself, folder.fold_path(path)) - } - ExprBreak(opt_name) => ExprBreak(opt_name.map(|label| { - respan(folder.new_span(label.span), folder.fold_name(label.node)) - })), - ExprAgain(opt_name) => ExprAgain(opt_name.map(|label| { - respan(folder.new_span(label.span), folder.fold_name(label.node)) - })), - ExprRet(e) => ExprRet(e.map(|x| folder.fold_expr(x))), - ExprInlineAsm(asm, outputs, inputs) => { - ExprInlineAsm(asm, - outputs.move_map(|x| folder.fold_expr(x)), - inputs.move_map(|x| folder.fold_expr(x))) - } - ExprStruct(path, fields, maybe_expr) => { - ExprStruct(folder.fold_path(path), - fields.move_map(|x| folder.fold_field(x)), - maybe_expr.map(|x| folder.fold_expr(x))) - } - }, - span: folder.new_span(span), - attrs: fold_attrs(attrs, folder), - } -} - -pub fn noop_fold_stmt(stmt: Stmt, folder: &mut T) -> Stmt { - let span = folder.new_span(stmt.span); - match stmt.node { - StmtDecl(d, id) => { - let id = folder.new_id(id); - Spanned { - node: StmtDecl(folder.fold_decl(d), id), - span: span - } - } - StmtExpr(e, id) => { - let id = folder.new_id(id); - Spanned { - node: StmtExpr(folder.fold_expr(e), id), - span: span, - } - } - StmtSemi(e, id) => { - let id = folder.new_id(id); - Spanned { - node: StmtSemi(folder.fold_expr(e), id), - span: span, - } - } - } -} diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index e22c9869ab176..0cfdbae1a50b0 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -67,7 +67,6 @@ macro_rules! hir_vec { pub mod check_attr; pub mod def; pub mod def_id; -pub mod fold; pub mod intravisit; pub mod lowering; pub mod map; diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs index 5d2b266ec4b7f..dda72ce57b4fa 100644 --- a/src/librustc_const_eval/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -40,11 +40,10 @@ use rustc_back::slice; use syntax::ast::{self, DUMMY_NODE_ID, NodeId}; use syntax::codemap::Spanned; use syntax_pos::{Span, DUMMY_SP}; -use rustc::hir::fold::{Folder, noop_fold_pat}; use rustc::hir::print::pat_to_string; use syntax::ptr::P; +use syntax::util::move_map::MoveMap; use rustc::util::common::ErrorReported; -use rustc::util::nodemap::FnvHashMap; pub const DUMMY_WILD_PAT: &'static Pat = &Pat { id: DUMMY_NODE_ID, @@ -182,7 +181,7 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &hir::Expr) { } } - let mut static_inliner = StaticInliner::new(cx.tcx, None); + let mut static_inliner = StaticInliner::new(cx.tcx); let inlined_arms = arms.iter().map(|arm| { (arm.pats.iter().map(|pat| { static_inliner.fold_pat((*pat).clone()) @@ -467,53 +466,30 @@ fn const_val_to_expr(value: &ConstVal) -> P { }) } -pub struct StaticInliner<'a, 'tcx: 'a> { - pub tcx: TyCtxt<'a, 'tcx, 'tcx>, - pub failed: bool, - pub renaming_map: Option<&'a mut FnvHashMap<(NodeId, Span), NodeId>>, +struct StaticInliner<'a, 'tcx: 'a> { + tcx: TyCtxt<'a, 'tcx, 'tcx>, + failed: bool } impl<'a, 'tcx> StaticInliner<'a, 'tcx> { - pub fn new<'b>(tcx: TyCtxt<'b, 'tcx, 'tcx>, - renaming_map: Option<&'b mut FnvHashMap<(NodeId, Span), NodeId>>) - -> StaticInliner<'b, 'tcx> { + pub fn new<'b>(tcx: TyCtxt<'b, 'tcx, 'tcx>) -> StaticInliner<'b, 'tcx> { StaticInliner { tcx: tcx, - failed: false, - renaming_map: renaming_map + failed: false } } } -struct RenamingRecorder<'map> { - substituted_node_id: NodeId, - origin_span: Span, - renaming_map: &'map mut FnvHashMap<(NodeId, Span), NodeId> -} - -impl<'v, 'map> Visitor<'v> for RenamingRecorder<'map> { - fn visit_id(&mut self, node_id: NodeId) { - let key = (node_id, self.origin_span); - self.renaming_map.insert(key, self.substituted_node_id); - } -} - -impl<'a, 'tcx> Folder for StaticInliner<'a, 'tcx> { +impl<'a, 'tcx> StaticInliner<'a, 'tcx> { fn fold_pat(&mut self, pat: P) -> P { - return match pat.node { + match pat.node { PatKind::Path(..) => { match self.tcx.expect_def(pat.id) { Def::AssociatedConst(did) | Def::Const(did) => { let substs = Some(self.tcx.node_id_item_substs(pat.id).substs); if let Some((const_expr, _)) = lookup_const_by_id(self.tcx, did, substs) { match const_expr_to_pat(self.tcx, const_expr, pat.id, pat.span) { - Ok(new_pat) => { - if let Some(ref mut map) = self.renaming_map { - // Record any renamings we do here - record_renamings(const_expr, &pat, map); - } - new_pat - } + Ok(new_pat) => return new_pat, Err(def_id) => { self.failed = true; self.tcx.sess.span_err( @@ -521,33 +497,62 @@ impl<'a, 'tcx> Folder for StaticInliner<'a, 'tcx> { &format!("constants of the type `{}` \ cannot be used in patterns", self.tcx.item_path_str(def_id))); - pat } } } else { self.failed = true; span_err!(self.tcx.sess, pat.span, E0158, "statics cannot be referenced in patterns"); - pat } } - _ => noop_fold_pat(pat, self) + _ => {} } } - _ => noop_fold_pat(pat, self) - }; + _ => {} + } - fn record_renamings(const_expr: &hir::Expr, - substituted_pat: &hir::Pat, - renaming_map: &mut FnvHashMap<(NodeId, Span), NodeId>) { - let mut renaming_recorder = RenamingRecorder { - substituted_node_id: substituted_pat.id, - origin_span: substituted_pat.span, - renaming_map: renaming_map, + pat.map(|Pat { id, node, span }| { + let node = match node { + PatKind::Binding(binding_mode, pth1, sub) => { + PatKind::Binding(binding_mode, pth1, sub.map(|x| self.fold_pat(x))) + } + PatKind::TupleStruct(pth, pats, ddpos) => { + PatKind::TupleStruct(pth, pats.move_map(|x| self.fold_pat(x)), ddpos) + } + PatKind::Struct(pth, fields, etc) => { + let fs = fields.move_map(|f| { + Spanned { + span: f.span, + node: hir::FieldPat { + name: f.node.name, + pat: self.fold_pat(f.node.pat), + is_shorthand: f.node.is_shorthand, + }, + } + }); + PatKind::Struct(pth, fs, etc) + } + PatKind::Tuple(elts, ddpos) => { + PatKind::Tuple(elts.move_map(|x| self.fold_pat(x)), ddpos) + } + PatKind::Box(inner) => PatKind::Box(self.fold_pat(inner)), + PatKind::Ref(inner, mutbl) => PatKind::Ref(self.fold_pat(inner), mutbl), + PatKind::Vec(before, slice, after) => { + PatKind::Vec(before.move_map(|x| self.fold_pat(x)), + slice.map(|x| self.fold_pat(x)), + after.move_map(|x| self.fold_pat(x))) + } + PatKind::Wild | + PatKind::Lit(_) | + PatKind::Range(..) | + PatKind::Path(..) => node }; - - renaming_recorder.visit_expr(const_expr); - } + Pat { + id: id, + node: node, + span: span + } + }) } } @@ -1047,7 +1052,7 @@ pub fn specialize<'a, 'b, 'tcx>( fn check_local(cx: &mut MatchCheckCtxt, loc: &hir::Local) { intravisit::walk_local(cx, loc); - let pat = StaticInliner::new(cx.tcx, None).fold_pat(loc.pat.clone()); + let pat = StaticInliner::new(cx.tcx).fold_pat(loc.pat.clone()); check_irrefutable(cx, &pat, false); // Check legality of move bindings and `@` patterns. diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 3983c098f306f..7eb7b24015e10 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -38,7 +38,6 @@ use rustc::middle::privacy::AccessLevels; use rustc::middle::resolve_lifetime::DefRegion::*; use rustc::hir::def::Def; use rustc::hir::def_id::{self, DefId, DefIndex, CRATE_DEF_INDEX}; -use rustc::hir::fold::Folder; use rustc::hir::print as pprust; use rustc::ty::subst::Substs; use rustc::ty::{self, AdtKind}; @@ -774,7 +773,20 @@ impl Lifetime { } impl Clean for hir::Lifetime { - fn clean(&self, _: &DocContext) -> Lifetime { + fn clean(&self, cx: &DocContext) -> Lifetime { + if let Some(tcx) = cx.tcx_opt() { + let def = tcx.named_region_map.defs.get(&self.id).cloned(); + match def { + Some(DefEarlyBoundRegion(_, node_id)) | + Some(DefLateBoundRegion(_, node_id)) | + Some(DefFreeRegion(_, node_id)) => { + if let Some(lt) = cx.lt_substs.borrow().get(&node_id).cloned() { + return lt; + } + } + _ => {} + } + } Lifetime(self.name.to_string()) } } @@ -1629,42 +1641,6 @@ impl From for PrimitiveType { } } -// Poor man's type parameter substitution at HIR level. -// Used to replace private type aliases in public signatures with their aliased types. -struct SubstAlias<'a, 'tcx: 'a> { - tcx: &'a ty::TyCtxt<'a, 'tcx, 'tcx>, - // Table type parameter definition -> substituted type - ty_substs: FnvHashMap, - // Table node id of lifetime parameter definition -> substituted lifetime - lt_substs: FnvHashMap, -} - -impl<'a, 'tcx: 'a, 'b: 'tcx> Folder for SubstAlias<'a, 'tcx> { - fn fold_ty(&mut self, ty: P) -> P { - if let hir::TyPath(..) = ty.node { - let def = self.tcx.expect_def(ty.id); - if let Some(new_ty) = self.ty_substs.get(&def).cloned() { - return P(new_ty); - } - } - hir::fold::noop_fold_ty(ty, self) - } - fn fold_lifetime(&mut self, lt: hir::Lifetime) -> hir::Lifetime { - let def = self.tcx.named_region_map.defs.get(<.id).cloned(); - match def { - Some(DefEarlyBoundRegion(_, node_id)) | - Some(DefLateBoundRegion(_, node_id)) | - Some(DefFreeRegion(_, node_id)) => { - if let Some(lt) = self.lt_substs.get(&node_id).cloned() { - return lt; - } - } - _ => {} - } - hir::fold::noop_fold_lifetime(lt, self) - } -} - impl Clean for hir::Ty { fn clean(&self, cx: &DocContext) -> Type { use rustc::hir::*; @@ -1696,43 +1672,47 @@ impl Clean for hir::Ty { }, TyTup(ref tys) => Tuple(tys.clean(cx)), TyPath(None, ref path) => { - if let Some(tcx) = cx.tcx_opt() { - // Substitute private type aliases - let def = tcx.expect_def(self.id); + let tcx_and_def = cx.tcx_opt().map(|tcx| (tcx, tcx.expect_def(self.id))); + if let Some((_, def)) = tcx_and_def { + if let Some(new_ty) = cx.ty_substs.borrow().get(&def).cloned() { + return new_ty; + } + } + + let tcx_and_alias = tcx_and_def.and_then(|(tcx, def)| { if let Def::TyAlias(def_id) = def { - if let Some(node_id) = tcx.map.as_local_node_id(def_id) { + // Substitute private type aliases + tcx.map.as_local_node_id(def_id).and_then(|node_id| { if !cx.access_levels.borrow().is_exported(def_id) { - let item = tcx.map.expect_item(node_id); - if let hir::ItemTy(ref ty, ref generics) = item.node { - let provided_params = &path.segments.last().unwrap().parameters; - let mut ty_substs = FnvHashMap(); - let mut lt_substs = FnvHashMap(); - for (i, ty_param) in generics.ty_params.iter().enumerate() { - let ty_param_def = tcx.expect_def(ty_param.id); - if let Some(ty) = provided_params.types().get(i).cloned() - .cloned() { - ty_substs.insert(ty_param_def, ty.unwrap()); - } else if let Some(default) = ty_param.default.clone() { - ty_substs.insert(ty_param_def, default.unwrap()); - } - } - for (i, lt_param) in generics.lifetimes.iter().enumerate() { - if let Some(lt) = provided_params.lifetimes().get(i) - .cloned() - .cloned() { - lt_substs.insert(lt_param.lifetime.id, lt); - } - } - let mut subst_alias = SubstAlias { - tcx: &tcx, - ty_substs: ty_substs, - lt_substs: lt_substs - }; - return subst_alias.fold_ty(ty.clone()).clean(cx); - } + Some((tcx, &tcx.map.expect_item(node_id).node)) + } else { + None } + }) + } else { + None + } + }); + if let Some((tcx, &hir::ItemTy(ref ty, ref generics))) = tcx_and_alias { + let provided_params = &path.segments.last().unwrap().parameters; + let mut ty_substs = FnvHashMap(); + let mut lt_substs = FnvHashMap(); + for (i, ty_param) in generics.ty_params.iter().enumerate() { + let ty_param_def = tcx.expect_def(ty_param.id); + if let Some(ty) = provided_params.types().get(i).cloned() + .cloned() { + ty_substs.insert(ty_param_def, ty.unwrap().clean(cx)); + } else if let Some(default) = ty_param.default.clone() { + ty_substs.insert(ty_param_def, default.unwrap().clean(cx)); + } + } + for (i, lt_param) in generics.lifetimes.iter().enumerate() { + if let Some(lt) = provided_params.lifetimes().get(i).cloned() + .cloned() { + lt_substs.insert(lt_param.lifetime.id, lt.clean(cx)); } } + return cx.enter_alias(ty_substs, lt_substs, || ty.clean(cx)); } resolve_type(cx, path.clean(cx), self.id) } diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index ab6858a09310f..399702003ea4f 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -14,6 +14,7 @@ use rustc_driver::{driver, target_features, abort_on_err}; use rustc::dep_graph::DepGraph; use rustc::session::{self, config}; use rustc::hir::def_id::{CrateNum, DefId}; +use rustc::hir::def::Def; use rustc::middle::privacy::AccessLevels; use rustc::ty::{self, TyCtxt}; use rustc::hir::map as hir_map; @@ -23,12 +24,13 @@ use rustc_trans::back::link; use rustc_resolve as resolve; use rustc_metadata::cstore::CStore; -use syntax::codemap; +use syntax::{ast, codemap}; use syntax::feature_gate::UnstableFeatures; use errors; use errors::emitter::ColorConfig; use std::cell::{RefCell, Cell}; +use std::mem; use std::rc::Rc; use visit_ast::RustdocVisitor; @@ -63,6 +65,14 @@ pub struct DocContext<'a, 'tcx: 'a> { pub renderinfo: RefCell, /// Later on moved through `clean::Crate` into `html::render::CACHE_KEY` pub external_traits: RefCell>, + + // The current set of type and lifetime substitutions, + // for expanding type aliases at the HIR level: + + /// Table type parameter definition -> substituted type + pub ty_substs: RefCell>, + /// Table node id of lifetime parameter definition -> substituted lifetime + pub lt_substs: RefCell>, } impl<'b, 'tcx> DocContext<'b, 'tcx> { @@ -84,6 +94,22 @@ impl<'b, 'tcx> DocContext<'b, 'tcx> { let tcx_opt = self.tcx_opt(); tcx_opt.expect("tcx not present") } + + /// Call the closure with the given parameters set as + /// the substitutions for a type alias' RHS. + pub fn enter_alias(&self, + ty_substs: FnvHashMap, + lt_substs: FnvHashMap, + f: F) -> R + where F: FnOnce() -> R { + let (old_tys, old_lts) = + (mem::replace(&mut *self.ty_substs.borrow_mut(), ty_substs), + mem::replace(&mut *self.lt_substs.borrow_mut(), lt_substs)); + let r = f(); + *self.ty_substs.borrow_mut() = old_tys; + *self.lt_substs.borrow_mut() = old_lts; + r + } } pub trait DocAccessLevels { @@ -179,12 +205,14 @@ pub fn run_core(search_paths: SearchPaths, map: &tcx.map, maybe_typed: Typed(tcx), input: input, - populated_crate_impls: RefCell::new(FnvHashSet()), + populated_crate_impls: Default::default(), deref_trait_did: Cell::new(None), deref_mut_trait_did: Cell::new(None), access_levels: RefCell::new(access_levels), - external_traits: RefCell::new(FnvHashMap()), - renderinfo: RefCell::new(Default::default()), + external_traits: Default::default(), + renderinfo: Default::default(), + ty_substs: Default::default(), + lt_substs: Default::default(), }; debug!("crate: {:?}", ctxt.map.krate()); diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 851cf95f9968f..3d2caeda1468d 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::cell::{RefCell, Cell}; +use std::cell::Cell; use std::env; use std::ffi::OsString; use std::io::prelude::*; @@ -28,7 +28,6 @@ use rustc::session::{self, config}; use rustc::session::config::{get_unstable_features_setting, OutputType, OutputTypes, Externs}; use rustc::session::search_paths::{SearchPaths, PathKind}; -use rustc::util::nodemap::{FnvHashMap, FnvHashSet}; use rustc_back::dynamic_lib::DynamicLibrary; use rustc_back::tempdir::TempDir; use rustc_driver::{driver, Compilation}; @@ -107,12 +106,14 @@ pub fn run(input: &str, map: &map, maybe_typed: core::NotTyped(&sess), input: input, - external_traits: RefCell::new(FnvHashMap()), - populated_crate_impls: RefCell::new(FnvHashSet()), + external_traits: Default::default(), + populated_crate_impls: Default::default(), deref_trait_did: Cell::new(None), deref_mut_trait_did: Cell::new(None), access_levels: Default::default(), renderinfo: Default::default(), + ty_substs: Default::default(), + lt_substs: Default::default(), }; let mut v = RustdocVisitor::new(&ctx); From 2ce0e6d4e7a8150c4bb1019b7a8276d373c9a307 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Thu, 1 Sep 2016 11:04:21 +0300 Subject: [PATCH 15/39] rustc_trans: use the TypeId hashing mechanism instead of metadata. --- src/librustc/middle/cstore.rs | 12 ------- src/librustc/ty/util.rs | 28 +++++++++------ src/librustc_metadata/csearch.rs | 8 ----- src/librustc_metadata/encoder.rs | 17 +-------- src/librustc_trans/back/symbol_names.rs | 47 ++++++++++++++----------- 5 files changed, 45 insertions(+), 67 deletions(-) diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 55a895b37ee33..513fa30861adb 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -258,11 +258,6 @@ pub trait CrateStore<'tcx> { // utility functions fn metadata_filename(&self) -> &str; fn metadata_section_name(&self, target: &Target) -> &str; - fn encode_type<'a>(&self, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - ty: Ty<'tcx>, - def_id_to_string: for<'b> fn(TyCtxt<'b, 'tcx, 'tcx>, DefId) -> String) - -> Vec; fn used_crates(&self, prefer: LinkagePreference) -> Vec<(CrateNum, Option)>; fn used_crate_source(&self, cnum: CrateNum) -> CrateSource; fn extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option; @@ -469,13 +464,6 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { // utility functions fn metadata_filename(&self) -> &str { bug!("metadata_filename") } fn metadata_section_name(&self, target: &Target) -> &str { bug!("metadata_section_name") } - fn encode_type<'a>(&self, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - ty: Ty<'tcx>, - def_id_to_string: for<'b> fn(TyCtxt<'b, 'tcx, 'tcx>, DefId) -> String) - -> Vec { - bug!("encode_type") - } fn used_crates(&self, prefer: LinkagePreference) -> Vec<(CrateNum, Option)> { vec![] } fn used_crate_source(&self, cnum: CrateNum) -> CrateSource { bug!("used_crate_source") } diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 2090877fb3c92..5c71f348b9925 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -352,12 +352,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// Creates a hash of the type `Ty` which will be the same no matter what crate /// context it's calculated within. This is used by the `type_id` intrinsic. pub fn type_id_hash(self, ty: Ty<'tcx>) -> u64 { - let mut hasher = TypeIdHasher { - tcx: self, - state: SipHasher::new() - }; + let mut hasher = TypeIdHasher::new(self, SipHasher::new()); hasher.visit_ty(ty); - hasher.state.finish() + hasher.finish() } /// Returns true if this ADT is a dtorck type. @@ -391,16 +388,27 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } -struct TypeIdHasher<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { +pub struct TypeIdHasher<'a, 'gcx: 'a+'tcx, 'tcx: 'a, H> { tcx: TyCtxt<'a, 'gcx, 'tcx>, - state: SipHasher + state: H } -impl<'a, 'gcx, 'tcx> TypeIdHasher<'a, 'gcx, 'tcx> { - fn hash(&mut self, x: T) { +impl<'a, 'gcx, 'tcx, H: Hasher> TypeIdHasher<'a, 'gcx, 'tcx, H> { + pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, state: H) -> Self { + TypeIdHasher { + tcx: tcx, + state: state + } + } + + pub fn hash(&mut self, x: T) { x.hash(&mut self.state); } + pub fn finish(self) -> u64 { + self.state.finish() + } + fn hash_discriminant_u8(&mut self, x: &T) { let v = unsafe { intrinsics::discriminant_value(x) @@ -419,7 +427,7 @@ impl<'a, 'gcx, 'tcx> TypeIdHasher<'a, 'gcx, 'tcx> { } } -impl<'a, 'gcx, 'tcx> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx, H: Hasher> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tcx, H> { fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool { // Distinguish between the Ty variants uniformly. self.hash_discriminant_u8(&ty.sty); diff --git a/src/librustc_metadata/csearch.rs b/src/librustc_metadata/csearch.rs index a30a5743c34f2..aae87005bf42e 100644 --- a/src/librustc_metadata/csearch.rs +++ b/src/librustc_metadata/csearch.rs @@ -677,14 +677,6 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { { loader::meta_section_name(target) } - fn encode_type<'a>(&self, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - ty: Ty<'tcx>, - def_id_to_string: for<'b> fn(TyCtxt<'b, 'tcx, 'tcx>, DefId) -> String) - -> Vec - { - encoder::encoded_ty(tcx, ty, def_id_to_string) - } fn used_crates(&self, prefer: LinkagePreference) -> Vec<(CrateNum, Option)> { diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 9773823c77ded..409982289d814 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -36,9 +36,8 @@ use rustc::session::config::{self, PanicStrategy, CrateTypeRustcMacro}; use rustc::util::nodemap::{FnvHashMap, NodeSet}; use rustc_serialize::{Encodable, SpecializedEncoder}; -use std::cell::RefCell; use std::io::prelude::*; -use std::io::{Cursor, SeekFrom}; +use std::io::SeekFrom; use std::ops::{Deref, DerefMut}; use std::rc::Rc; use std::u32; @@ -1891,17 +1890,3 @@ fn encode_metadata_inner(ecx: &mut EncodeContext, krate: &hir::Crate) { println!(" total bytes: {}", stats.total_bytes); } } - -// Get the encoded string for a type -pub fn encoded_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - t: Ty<'tcx>, - def_id_to_string: for<'b> fn(TyCtxt<'b, 'tcx, 'tcx>, DefId) -> String) - -> Vec { - let mut wr = Cursor::new(Vec::new()); - tyencode::enc_ty(&mut wr, &tyencode::ctxt { - ds: def_id_to_string, - tcx: tcx, - abbrevs: &RefCell::new(FnvHashMap()) - }, t); - wr.into_inner() -} diff --git a/src/librustc_trans/back/symbol_names.rs b/src/librustc_trans/back/symbol_names.rs index ab1474c235132..500e9edebf3fe 100644 --- a/src/librustc_trans/back/symbol_names.rs +++ b/src/librustc_trans/back/symbol_names.rs @@ -102,9 +102,10 @@ use monomorphize::Instance; use util::sha2::{Digest, Sha256}; use rustc::middle::weak_lang_items; -use rustc::hir::def_id::{DefId, LOCAL_CRATE}; +use rustc::hir::def_id::LOCAL_CRATE; use rustc::hir::map as hir_map; -use rustc::ty::{Ty, TyCtxt, TypeFoldable}; +use rustc::ty::{self, Ty, TypeFoldable}; +use rustc::ty::fold::TypeVisitor; use rustc::ty::item_path::{self, ItemPathBuffer, RootMode}; use rustc::ty::subst::Substs; use rustc::hir::map::definitions::{DefPath, DefPathData}; @@ -114,9 +115,18 @@ use syntax::attr; use syntax::parse::token::{self, InternedString}; use serialize::hex::ToHex; -pub fn def_id_to_string<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> String { - let def_path = tcx.def_path(def_id); - def_path.to_string(tcx) +use std::hash::Hasher; + +struct Sha256Hasher<'a>(&'a mut Sha256); + +impl<'a> Hasher for Sha256Hasher<'a> { + fn write(&mut self, msg: &[u8]) { + self.0.input(msg) + } + + fn finish(&self) -> u64 { + bug!("Sha256Hasher::finish should not be called"); + } } fn get_symbol_hash<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, @@ -132,48 +142,43 @@ fn get_symbol_hash<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, // values for generic type parameters, // if any. - substs: Option<&Substs<'tcx>>) + substs: Option<&'tcx Substs<'tcx>>) -> String { debug!("get_symbol_hash(def_path={:?}, parameters={:?})", def_path, substs); let tcx = scx.tcx(); - return record_time(&tcx.sess.perf_stats.symbol_hash_time, || { - let mut hash_state = scx.symbol_hasher().borrow_mut(); - + let mut hash_state = scx.symbol_hasher().borrow_mut(); + record_time(&tcx.sess.perf_stats.symbol_hash_time, || { hash_state.reset(); + let mut hasher = ty::util::TypeIdHasher::new(tcx, Sha256Hasher(&mut hash_state)); // the main symbol name is not necessarily unique; hash in the // compiler's internal def-path, guaranteeing each symbol has a // truly unique path - hash_state.input_str(&def_path.to_string(tcx)); + hasher.hash(def_path.to_string(tcx)); // Include the main item-type. Note that, in this case, the // assertions about `needs_subst` may not hold, but this item-type // ought to be the same for every reference anyway. assert!(!item_type.has_erasable_regions()); - let encoded_item_type = tcx.sess.cstore.encode_type(tcx, item_type, def_id_to_string); - hash_state.input(&encoded_item_type[..]); + hasher.visit_ty(item_type); // also include any type parameters (for generic items) if let Some(substs) = substs { - for t in substs.types() { - assert!(!t.has_erasable_regions()); - assert!(!t.needs_subst()); - let encoded_type = tcx.sess.cstore.encode_type(tcx, t, def_id_to_string); - hash_state.input(&encoded_type[..]); - } + assert!(!substs.has_erasable_regions()); + assert!(!substs.needs_subst()); + substs.visit_with(&mut hasher); } - - format!("h{}", truncated_hash_result(&mut *hash_state)) }); - fn truncated_hash_result(symbol_hasher: &mut Sha256) -> String { let output = symbol_hasher.result_bytes(); // 64 bits should be enough to avoid collisions. output[.. 8].to_hex() } + + format!("h{}", truncated_hash_result(&mut hash_state)) } impl<'a, 'tcx> Instance<'tcx> { From 0863012fb9b709aee34190d902f0fce5d34eef9e Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Thu, 1 Sep 2016 16:55:33 +0300 Subject: [PATCH 16/39] Remove librbml and the RBML-tagged auto-encoder/decoder. --- mk/crates.mk | 9 +- mk/tests.mk | 2 +- src/librbml/Cargo.toml | 13 - src/librbml/lib.rs | 63 --- src/librustc/Cargo.toml | 1 - src/librustc/lib.rs | 1 - src/librustc/middle/cstore.rs | 6 +- src/librustc_incremental/Cargo.toml | 3 +- src/librustc_incremental/lib.rs | 1 - src/librustc_incremental/persist/hash.rs | 5 +- src/librustc_incremental/persist/load.rs | 5 +- src/librustc_incremental/persist/save.rs | 2 +- src/librustc_metadata/Cargo.toml | 1 - src/librustc_metadata/astencode.rs | 2 +- src/librustc_metadata/common.rs | 9 +- src/librustc_metadata/csearch.rs | 21 +- src/librustc_metadata/decoder.rs | 59 ++- src/librustc_metadata/encoder.rs | 244 +++++---- src/librustc_metadata/index.rs | 6 +- src/librustc_metadata/index_builder.rs | 13 +- src/librustc_metadata/lib.rs | 3 - src/librustc_metadata/rbml/reader.rs | 595 ++-------------------- src/librustc_metadata/rbml/writer.rs | 379 ++------------ src/librustc_metadata/tydecode.rs | 2 +- src/librustc_metadata/tyencode.rs | 5 +- src/librustc_trans/base.rs | 3 +- src/{librbml => libserialize}/leb128.rs | 0 src/libserialize/lib.rs | 3 + src/{librbml => libserialize}/opaque.rs | 260 +--------- src/libserialize/serialize.rs | 194 ++++--- src/rustc/Cargo.lock | 11 - src/test/run-pass-fulldeps/issue-11881.rs | 6 +- 32 files changed, 411 insertions(+), 1516 deletions(-) delete mode 100644 src/librbml/Cargo.toml delete mode 100644 src/librbml/lib.rs rename src/{librbml => libserialize}/leb128.rs (100%) rename src/{librbml => libserialize}/opaque.rs (64%) diff --git a/mk/crates.mk b/mk/crates.mk index d2c79441d866f..86bb3a8ca0ccc 100644 --- a/mk/crates.mk +++ b/mk/crates.mk @@ -61,7 +61,7 @@ RUSTC_CRATES := rustc rustc_typeck rustc_mir rustc_borrowck rustc_resolve rustc_ rustc_plugin rustc_metadata rustc_passes rustc_save_analysis \ rustc_const_eval rustc_const_math rustc_incremental rustc_macro HOST_CRATES := syntax syntax_ext proc_macro syntax_pos $(RUSTC_CRATES) rustdoc fmt_macros \ - flate arena graphviz rbml log serialize + flate arena graphviz log serialize TOOLS := compiletest rustdoc rustc rustbook error_index_generator DEPS_core := @@ -96,7 +96,6 @@ DEPS_getopts := std DEPS_graphviz := std DEPS_log := std DEPS_num := std -DEPS_rbml := std log serialize DEPS_serialize := std log DEPS_term := std DEPS_test := std getopts term native:rust_test_helpers @@ -110,7 +109,7 @@ DEPS_rustc_const_math := std syntax log serialize DEPS_rustc_const_eval := rustc_const_math rustc syntax log serialize \ rustc_back graphviz syntax_pos -DEPS_rustc := syntax fmt_macros flate arena serialize getopts rbml \ +DEPS_rustc := syntax fmt_macros flate arena serialize getopts \ log graphviz rustc_llvm rustc_back rustc_data_structures\ rustc_const_math syntax_pos rustc_errors DEPS_rustc_back := std syntax flate log libc @@ -126,7 +125,7 @@ DEPS_rustc_errors := log libc serialize syntax_pos DEPS_rustc_lint := rustc log syntax syntax_pos rustc_const_eval DEPS_rustc_llvm := native:rustllvm libc std rustc_bitflags DEPS_rustc_macro := std syntax -DEPS_rustc_metadata := rustc syntax syntax_pos rustc_errors rbml rustc_const_math \ +DEPS_rustc_metadata := rustc syntax syntax_pos rustc_errors rustc_const_math \ rustc_macro syntax_ext DEPS_rustc_passes := syntax syntax_pos rustc core rustc_const_eval rustc_errors DEPS_rustc_mir := rustc syntax syntax_pos rustc_const_math rustc_const_eval rustc_bitflags @@ -137,7 +136,7 @@ DEPS_rustc_privacy := rustc log syntax syntax_pos DEPS_rustc_trans := arena flate getopts graphviz libc rustc rustc_back \ log syntax serialize rustc_llvm rustc_platform_intrinsics \ rustc_const_math rustc_const_eval rustc_incremental rustc_errors syntax_pos -DEPS_rustc_incremental := rbml rustc syntax_pos serialize rustc_data_structures +DEPS_rustc_incremental := rustc syntax_pos serialize rustc_data_structures DEPS_rustc_save_analysis := rustc log syntax syntax_pos serialize DEPS_rustc_typeck := rustc syntax syntax_pos rustc_platform_intrinsics rustc_const_math \ rustc_const_eval rustc_errors diff --git a/mk/tests.mk b/mk/tests.mk index c135aa9b8fb95..fc1f4b5561a78 100644 --- a/mk/tests.mk +++ b/mk/tests.mk @@ -27,7 +27,7 @@ TEST_TARGET_CRATES = $(filter-out core rustc_unicode alloc_system libc \ panic_abort,$(TARGET_CRATES)) \ collectionstest coretest TEST_DOC_CRATES = $(DOC_CRATES) arena flate fmt_macros getopts graphviz \ - log rand rbml serialize syntax term test + log rand serialize syntax term test TEST_HOST_CRATES = $(filter-out rustc_typeck rustc_borrowck rustc_resolve \ rustc_trans rustc_lint,\ $(HOST_CRATES)) diff --git a/src/librbml/Cargo.toml b/src/librbml/Cargo.toml deleted file mode 100644 index ab89ac2b7a1eb..0000000000000 --- a/src/librbml/Cargo.toml +++ /dev/null @@ -1,13 +0,0 @@ -[package] -authors = ["The Rust Project Developers"] -name = "rbml" -version = "0.0.0" - -[lib] -name = "rbml" -path = "lib.rs" -crate-type = ["dylib"] - -[dependencies] -log = { path = "../liblog" } -serialize = { path = "../libserialize" } diff --git a/src/librbml/lib.rs b/src/librbml/lib.rs deleted file mode 100644 index 65259f903a99c..0000000000000 --- a/src/librbml/lib.rs +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Skeleton of RBML (Really Bad Markup Language). -//! See `src/librustc_metadata/reader.rs` for more details. - -#![crate_name = "rbml"] -#![unstable(feature = "rustc_private", issue = "27812")] -#![crate_type = "rlib"] -#![crate_type = "dylib"] -#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", - html_favicon_url = "https://doc.rust-lang.org/favicon.ico", - html_root_url = "https://doc.rust-lang.org/nightly/", - html_playground_url = "https://play.rust-lang.org/", - test(attr(deny(warnings))))] -#![cfg_attr(not(stage0), deny(warnings))] - -#![feature(rustc_private)] -#![feature(staged_api)] -#![feature(question_mark)] - -#![cfg_attr(test, feature(test))] - -extern crate serialize; - -#[cfg(test)] -extern crate serialize as rustc_serialize; // Used by RustcEncodable - -#[macro_use] -extern crate log; - -#[cfg(test)] -extern crate test; - -pub mod opaque; -pub mod leb128; - -pub use self::Error::*; - -use std::fmt; - -#[derive(Debug)] -pub enum Error { - IntTooBig(usize), - InvalidTag(usize), - Expected(String), - IoError(std::io::Error), - ApplicationError(String), -} - -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - // FIXME: this should be a more useful display form - fmt::Debug::fmt(self, f) - } -} diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml index aaef8e8423cbe..578ef68b00386 100644 --- a/src/librustc/Cargo.toml +++ b/src/librustc/Cargo.toml @@ -14,7 +14,6 @@ flate = { path = "../libflate" } fmt_macros = { path = "../libfmt_macros" } graphviz = { path = "../libgraphviz" } log = { path = "../liblog" } -rbml = { path = "../librbml" } rustc_back = { path = "../librustc_back" } rustc_bitflags = { path = "../librustc_bitflags" } rustc_const_math = { path = "../librustc_const_math" } diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index d2a2f8a972d96..c34286f0195bf 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -50,7 +50,6 @@ extern crate fmt_macros; extern crate getopts; extern crate graphviz; extern crate libc; -extern crate rbml; extern crate rustc_llvm as llvm; extern crate rustc_back; extern crate rustc_data_structures; diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 513fa30861adb..1d6047579f6cf 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -265,8 +265,7 @@ pub trait CrateStore<'tcx> { reexports: &def::ExportMap, link_meta: &LinkMeta, reachable: &NodeSet, - mir_map: &MirMap<'tcx>, - krate: &hir::Crate) -> Vec; + mir_map: &MirMap<'tcx>) -> Vec; fn metadata_encoding_version(&self) -> &[u8]; } @@ -472,8 +471,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { reexports: &def::ExportMap, link_meta: &LinkMeta, reachable: &NodeSet, - mir_map: &MirMap<'tcx>, - krate: &hir::Crate) -> Vec { vec![] } + mir_map: &MirMap<'tcx>) -> Vec { vec![] } fn metadata_encoding_version(&self) -> &[u8] { bug!("metadata_encoding_version") } } diff --git a/src/librustc_incremental/Cargo.toml b/src/librustc_incremental/Cargo.toml index 7db1a6348b27c..e3ee752754504 100644 --- a/src/librustc_incremental/Cargo.toml +++ b/src/librustc_incremental/Cargo.toml @@ -10,10 +10,9 @@ crate-type = ["dylib"] [dependencies] graphviz = { path = "../libgraphviz" } -rbml = { path = "../librbml" } rustc = { path = "../librustc" } rustc_data_structures = { path = "../librustc_data_structures" } serialize = { path = "../libserialize" } log = { path = "../liblog" } syntax = { path = "../libsyntax" } -syntax_pos = { path = "../libsyntax_pos" } \ No newline at end of file +syntax_pos = { path = "../libsyntax_pos" } diff --git a/src/librustc_incremental/lib.rs b/src/librustc_incremental/lib.rs index 1f823eedda0dd..42b5657e212b0 100644 --- a/src/librustc_incremental/lib.rs +++ b/src/librustc_incremental/lib.rs @@ -27,7 +27,6 @@ #![feature(core_intrinsics)] extern crate graphviz; -extern crate rbml; #[macro_use] extern crate rustc; extern crate rustc_data_structures; extern crate serialize as rustc_serialize; diff --git a/src/librustc_incremental/persist/hash.rs b/src/librustc_incremental/persist/hash.rs index 6dcf2c288914c..5a4716e45f6e1 100644 --- a/src/librustc_incremental/persist/hash.rs +++ b/src/librustc_incremental/persist/hash.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use rbml::Error; -use rbml::opaque::Decoder; use rustc::dep_graph::DepNode; use rustc::hir::def_id::{CrateNum, DefId}; use rustc::hir::svh::Svh; @@ -17,6 +15,7 @@ use rustc::ty::TyCtxt; use rustc_data_structures::fnv::FnvHashMap; use rustc_data_structures::flock; use rustc_serialize::Decodable; +use rustc_serialize::opaque::Decoder; use std::io::{ErrorKind, Read}; use std::fs::File; @@ -188,7 +187,7 @@ impl<'a, 'tcx> HashContext<'a, 'tcx> { fn load_from_data(&mut self, cnum: CrateNum, data: &[u8], - expected_svh: Svh) -> Result<(), Error> { + expected_svh: Svh) -> Result<(), String> { debug!("load_from_data(cnum={})", cnum); // Load up the hashes for the def-ids from this crate. diff --git a/src/librustc_incremental/persist/load.rs b/src/librustc_incremental/persist/load.rs index 6e6464e49683a..b051e6c5ab73a 100644 --- a/src/librustc_incremental/persist/load.rs +++ b/src/librustc_incremental/persist/load.rs @@ -10,14 +10,13 @@ //! Code to save/load the dep-graph from files. -use rbml::Error; -use rbml::opaque::Decoder; use rustc::dep_graph::DepNode; use rustc::hir::def_id::DefId; use rustc::session::Session; use rustc::ty::TyCtxt; use rustc_data_structures::fnv::FnvHashSet; use rustc_serialize::Decodable as RustcDecodable; +use rustc_serialize::opaque::Decoder; use std::io::Read; use std::fs::{self, File}; use std::path::{Path}; @@ -121,7 +120,7 @@ pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, incremental_hashes_map: &IncrementalHashesMap, dep_graph_data: &[u8], work_products_data: &[u8]) - -> Result<(), Error> + -> Result<(), String> { // Decode the list of work_products let mut work_product_decoder = Decoder::new(work_products_data, 0); diff --git a/src/librustc_incremental/persist/save.rs b/src/librustc_incremental/persist/save.rs index 41212d8e138da..5b45874840f56 100644 --- a/src/librustc_incremental/persist/save.rs +++ b/src/librustc_incremental/persist/save.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use rbml::opaque::Encoder; use rustc::dep_graph::DepNode; use rustc::hir::def_id::DefId; use rustc::hir::svh::Svh; @@ -16,6 +15,7 @@ use rustc::session::Session; use rustc::ty::TyCtxt; use rustc_data_structures::fnv::FnvHashMap; use rustc_serialize::Encodable as RustcEncodable; +use rustc_serialize::opaque::Encoder; use std::hash::{Hash, Hasher, SipHasher}; use std::io::{self, Cursor, Write}; use std::fs::{self, File}; diff --git a/src/librustc_metadata/Cargo.toml b/src/librustc_metadata/Cargo.toml index d70510896b96e..fede6f663418c 100644 --- a/src/librustc_metadata/Cargo.toml +++ b/src/librustc_metadata/Cargo.toml @@ -11,7 +11,6 @@ crate-type = ["dylib"] [dependencies] flate = { path = "../libflate" } log = { path = "../liblog" } -rbml = { path = "../librbml" } rustc = { path = "../librustc" } rustc_back = { path = "../librustc_back" } rustc_bitflags = { path = "../librustc_bitflags" } diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs index ce15ec6a29d28..f00c4b82a8518 100644 --- a/src/librustc_metadata/astencode.rs +++ b/src/librustc_metadata/astencode.rs @@ -217,7 +217,7 @@ fn encode_side_tables_for_id(ecx: &mut EncodeContext, id: ast::NodeId) { } fn decode_side_tables(dcx: &mut DecodeContext, ast_doc: rbml::Doc) { - while dcx.position() < ast_doc.end { + while dcx.opaque.position() < ast_doc.end { let table = Decodable::decode(dcx).unwrap(); let id = Decodable::decode(dcx).unwrap(); debug!("decode_side_tables: entry for id={}, table={:?}", id, table); diff --git a/src/librustc_metadata/common.rs b/src/librustc_metadata/common.rs index 512f4ca6584c6..3b63ee6b5fa89 100644 --- a/src/librustc_metadata/common.rs +++ b/src/librustc_metadata/common.rs @@ -10,12 +10,9 @@ #![allow(non_camel_case_types, non_upper_case_globals)] -// RBML enum definitions and utils shared by the encoder and decoder -// -// 0x00..0x1f: reserved for RBML generic type tags -// 0x20..0xef: free for use, preferred for frequent tags -// 0xf0..0xff: internally used by RBML to encode 0x100..0xfff in two bytes -// 0x100..0xfff: free for use, preferred for infrequent tags +pub const tag_opaque: usize = 0x00; + +// GAP 0x01...0x19 pub const tag_items: usize = 0x100; // top-level only diff --git a/src/librustc_metadata/csearch.rs b/src/librustc_metadata/csearch.rs index aae87005bf42e..b291c4927aa3f 100644 --- a/src/librustc_metadata/csearch.rs +++ b/src/librustc_metadata/csearch.rs @@ -13,7 +13,6 @@ use common; use decoder; use encoder; use loader; -use rbml; use middle::cstore::{InlinedItem, CrateStore, CrateSource, ChildItem, ExternCrate, DefLike}; use middle::cstore::{NativeLibraryKind, LinkMeta, LinkagePreference}; @@ -30,7 +29,6 @@ use rustc::mir::mir_map::MirMap; use rustc::util::nodemap::{FnvHashMap, NodeSet, DefIdMap}; use rustc::session::config::PanicStrategy; -use std::cell::RefCell; use std::rc::Rc; use std::path::PathBuf; use syntax::ast; @@ -697,22 +695,9 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { reexports: &def::ExportMap, link_meta: &LinkMeta, reachable: &NodeSet, - mir_map: &MirMap<'tcx>, - krate: &hir::Crate) -> Vec - { - let type_abbrevs = RefCell::new(FnvHashMap()); - let ecx = encoder::EncodeContext { - rbml_w: rbml::writer::Encoder::new(), - tcx: tcx, - reexports: reexports, - link_meta: link_meta, - cstore: self, - reachable: reachable, - mir_map: mir_map, - type_abbrevs: &type_abbrevs, - }; - encoder::encode_metadata(ecx, krate) - + mir_map: &MirMap<'tcx>) -> Vec + { + encoder::encode_metadata(tcx, self, reexports, link_meta, reachable, mir_map) } fn metadata_encoding_version(&self) -> &[u8] diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 1bec365e472b1..ba593e5be9980 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -45,14 +45,14 @@ use rustc_const_math::ConstInt; use rustc::mir::repr::Mir; use std::io; -use std::ops::{Deref, DerefMut}; use std::rc::Rc; use std::str; use std::u32; use rbml::reader; use rbml; -use rustc_serialize::{Decodable, SpecializedDecoder}; +use rustc_serialize::{Decodable, SpecializedDecoder, opaque}; +use rustc_serialize as serialize; use syntax::attr; use syntax::parse::token; use syntax::ast::{self, NodeId}; @@ -60,7 +60,7 @@ use syntax::print::pprust; use syntax_pos::{self, Span, BytePos, NO_EXPANSION}; pub struct DecodeContext<'a, 'tcx: 'a> { - rbml_r: rbml::reader::Decoder<'a>, + pub opaque: opaque::Decoder<'a>, pub tcx: Option>, pub cdata: Option<&'a cstore::CrateMetadata>, pub from_id_range: IdRange, @@ -76,7 +76,7 @@ impl<'doc> rbml::Doc<'doc> { max: NodeId::from_u32(u32::MAX) }; DecodeContext { - rbml_r: reader::Decoder::new(self), + opaque: opaque::Decoder::new(self.data, self.start), cdata: None, tcx: None, from_id_range: id_range, @@ -98,24 +98,49 @@ impl<'a, 'tcx> DecodeContext<'a, 'tcx> { fn read_ty_encoded(&mut self, op: F) -> R where F: for<'x> FnOnce(&mut TyDecoder<'x,'tcx>) -> R { - self.read_opaque(|this, doc| { - Ok(op(&mut TyDecoder::with_doc( - this.tcx(), this.cdata().cnum, doc, - &mut |d| translate_def_id(this.cdata(), d)))) - }).unwrap() + let pos = self.opaque.position(); + let doc = rbml::Doc::at(self.opaque.data, pos); + self.opaque.advance(doc.end - pos); + op(&mut TyDecoder::with_doc(self.tcx(), self.cdata().cnum, doc, + &mut |d| translate_def_id(self.cdata(), d))) } } -impl<'a, 'tcx> Deref for DecodeContext<'a, 'tcx> { - type Target = rbml::reader::Decoder<'a>; - fn deref(&self) -> &Self::Target { - &self.rbml_r +macro_rules! decoder_methods { + ($($name:ident -> $ty:ty;)*) => { + $(fn $name(&mut self) -> Result<$ty, Self::Error> { + self.opaque.$name() + })* } } -impl<'a, 'tcx> DerefMut for DecodeContext<'a, 'tcx> { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.rbml_r +impl<'doc, 'tcx> serialize::Decoder for ::decoder::DecodeContext<'doc, 'tcx> { + type Error = as serialize::Decoder>::Error; + + decoder_methods! { + read_nil -> (); + + read_u64 -> u64; + read_u32 -> u32; + read_u16 -> u16; + read_u8 -> u8; + read_usize -> usize; + + read_i64 -> i64; + read_i32 -> i32; + read_i16 -> i16; + read_i8 -> i8; + read_isize -> isize; + + read_bool -> bool; + read_f64 -> f64; + read_f32 -> f32; + read_char -> char; + read_str -> String; + } + + fn error(&mut self, err: &str) -> Self::Error { + self.opaque.error(err) } } @@ -256,7 +281,7 @@ pub type Cmd<'a> = &'a CrateMetadata; impl CrateMetadata { fn get_item(&self, item_id: DefIndex) -> Option { self.index.lookup_item(self.data(), item_id).map(|pos| { - reader::doc_at(self.data(), pos as usize).unwrap().doc + rbml::Doc::at(self.data(), pos as usize) }) } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 409982289d814..4b603fcb1055d 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -35,9 +35,10 @@ use rustc::mir::mir_map::MirMap; use rustc::session::config::{self, PanicStrategy, CrateTypeRustcMacro}; use rustc::util::nodemap::{FnvHashMap, NodeSet}; -use rustc_serialize::{Encodable, SpecializedEncoder}; +use rustc_serialize::{Encodable, SpecializedEncoder, opaque}; +use rustc_serialize as serialize; use std::io::prelude::*; -use std::io::SeekFrom; +use std::io::Cursor; use std::ops::{Deref, DerefMut}; use std::rc::Rc; use std::u32; @@ -55,7 +56,7 @@ use rustc::hir::map::DefKey; use super::index_builder::{FromId, IndexBuilder, ItemContentBuilder, Untracked, XRef}; pub struct EncodeContext<'a, 'tcx: 'a> { - pub rbml_w: rbml::writer::Encoder, + pub rbml_w: rbml::writer::Encoder<'a>, pub tcx: TyCtxt<'a, 'tcx, 'tcx>, pub reexports: &'a def::ExportMap, pub link_meta: &'a LinkMeta, @@ -66,7 +67,7 @@ pub struct EncodeContext<'a, 'tcx: 'a> { } impl<'a, 'tcx> Deref for EncodeContext<'a, 'tcx> { - type Target = rbml::writer::Encoder; + type Target = rbml::writer::Encoder<'a>; fn deref(&self) -> &Self::Target { &self.rbml_w } @@ -78,21 +79,61 @@ impl<'a, 'tcx> DerefMut for EncodeContext<'a, 'tcx> { } } +macro_rules! encoder_methods { + ($($name:ident($ty:ty);)*) => { + $(fn $name(&mut self, value: $ty) -> Result<(), Self::Error> { + self.opaque.$name(value) + })* + } +} + +impl<'a, 'tcx> serialize::Encoder for ::encoder::EncodeContext<'a, 'tcx> { + type Error = as serialize::Encoder>::Error; + + fn emit_nil(&mut self) -> Result<(), Self::Error> { + Ok(()) + } + + encoder_methods! { + emit_usize(usize); + emit_u64(u64); + emit_u32(u32); + emit_u16(u16); + emit_u8(u8); + + emit_isize(isize); + emit_i64(i64); + emit_i32(i32); + emit_i16(i16); + emit_i8(i8); + + emit_bool(bool); + emit_f64(f64); + emit_f32(f32); + emit_char(char); + emit_str(&str); + } +} + impl<'a, 'tcx> SpecializedEncoder> for EncodeContext<'a, 'tcx> { fn specialized_encode(&mut self, ty: &Ty<'tcx>) -> Result<(), Self::Error> { let cx = self.ty_str_ctxt(); - self.emit_opaque(|opaque_encoder| { - Ok(tyencode::enc_ty(opaque_encoder.cursor, &cx, ty)) - }) + + self.start_tag(tag_opaque)?; + tyencode::enc_ty(&mut self.rbml_w.opaque.cursor, &cx, ty); + self.mark_stable_position(); + self.end_tag() } } impl<'a, 'tcx> SpecializedEncoder<&'tcx Substs<'tcx>> for EncodeContext<'a, 'tcx> { fn specialized_encode(&mut self, substs: &&'tcx Substs<'tcx>) -> Result<(), Self::Error> { let cx = self.ty_str_ctxt(); - self.emit_opaque(|opaque_encoder| { - Ok(tyencode::enc_substs(opaque_encoder.cursor, &cx, substs)) - }) + + self.start_tag(tag_opaque)?; + tyencode::enc_substs(&mut self.rbml_w.opaque.cursor, &cx, substs); + self.mark_stable_position(); + self.end_tag() } } @@ -124,7 +165,7 @@ fn encode_trait_ref<'a, 'tcx>(ecx: &mut EncodeContext<'a, 'tcx>, tag: usize) { let cx = ecx.ty_str_ctxt(); ecx.start_tag(tag); - tyencode::enc_trait_ref(&mut ecx.writer, &cx, trait_ref); + tyencode::enc_trait_ref(&mut ecx.opaque.cursor, &cx, trait_ref); ecx.mark_stable_position(); ecx.end_tag(); } @@ -173,7 +214,7 @@ fn encode_variant_id(ecx: &mut EncodeContext, vid: DefId) { fn write_closure_type<'a, 'tcx>(ecx: &mut EncodeContext<'a, 'tcx>, closure_type: &ty::ClosureTy<'tcx>) { let cx = ecx.ty_str_ctxt(); - tyencode::enc_closure_ty(&mut ecx.writer, &cx, closure_type); + tyencode::enc_closure_ty(&mut ecx.opaque.cursor, &cx, closure_type); ecx.mark_stable_position(); } @@ -181,7 +222,7 @@ impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { fn encode_type(&mut self, typ: Ty<'tcx>) { let cx = self.ty_str_ctxt(); self.start_tag(tag_items_data_item_type); - tyencode::enc_ty(&mut self.writer, &cx, typ); + tyencode::enc_ty(&mut self.opaque.cursor, &cx, typ); self.mark_stable_position(); self.end_tag(); } @@ -480,7 +521,7 @@ impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { { let cx = self.ty_str_ctxt(); self.start_tag(tag_item_generics); - tyencode::enc_generics(&mut self.writer, &cx, generics); + tyencode::enc_generics(&mut self.opaque.cursor, &cx, generics); self.mark_stable_position(); self.end_tag(); self.encode_predicates(predicates, tag_item_predicates); @@ -829,7 +870,7 @@ fn encode_xrefs<'a, 'tcx>(ecx: &mut EncodeContext<'a, 'tcx>, xref_positions[id as usize] = ecx.mark_stable_position() as u32; match xref { XRef::Predicate(p) => { - tyencode::enc_predicate(&mut ecx.writer, &cx, &p) + tyencode::enc_predicate(&mut ecx.opaque.cursor, &cx, &p) } } } @@ -837,7 +878,7 @@ fn encode_xrefs<'a, 'tcx>(ecx: &mut EncodeContext<'a, 'tcx>, ecx.end_tag(); ecx.start_tag(tag_xref_index); - index::write_dense_index(xref_positions, &mut ecx.writer); + index::write_dense_index(xref_positions, &mut ecx.opaque.cursor); ecx.end_tag(); } @@ -1396,7 +1437,7 @@ fn encode_info_for_items<'a, 'tcx>(ecx: &mut EncodeContext<'a, 'tcx>) fn encode_item_index(ecx: &mut EncodeContext, index: IndexData) { ecx.start_tag(tag_index); - index.write_index(&mut ecx.writer); + index.write_index(&mut ecx.opaque.cursor); ecx.end_tag(); } @@ -1710,15 +1751,33 @@ fn encode_panic_strategy(ecx: &mut EncodeContext) { } } -pub fn encode_metadata(mut ecx: EncodeContext, krate: &hir::Crate) -> Vec { - encode_metadata_inner(&mut ecx, krate); +pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + cstore: &cstore::CStore, + reexports: &def::ExportMap, + link_meta: &LinkMeta, + reachable: &NodeSet, + mir_map: &MirMap<'tcx>) -> Vec { + let mut cursor = Cursor::new(vec![]); + cursor.write_all(&[0, 0, 0, 0]).unwrap(); + cursor.write_all(metadata_encoding_version).unwrap(); + // Will be filed with the length after encoding the crate. + cursor.write_all(&[0, 0, 0, 0]).unwrap(); + + encode_metadata_inner(&mut EncodeContext { + rbml_w: rbml::writer::Encoder::new(&mut cursor), + tcx: tcx, + reexports: reexports, + link_meta: link_meta, + cstore: cstore, + reachable: reachable, + mir_map: mir_map, + type_abbrevs: &Default::default(), + }); // RBML compacts the encoded bytes whenever appropriate, // so there are some garbages left after the end of the data. - let metalen = ecx.rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() as usize; - let mut v = ecx.rbml_w.writer.into_inner(); - v.truncate(metalen); - assert_eq!(v.len(), metalen); + let meta_len = cursor.position() as usize; + cursor.get_mut().truncate(meta_len); // And here we run into yet another obscure archive bug: in which metadata // loaded from archives may have trailing garbage bytes. Awhile back one of @@ -1744,55 +1803,17 @@ pub fn encode_metadata(mut ecx: EncodeContext, krate: &hir::Crate) -> Vec { // this metadata, there are 4 zero bytes at the start, which are // treated as a length of 0 by old compilers. - let len = v.len(); - let mut result = vec![]; - result.push(0); - result.push(0); - result.push(0); - result.push(0); - result.extend(metadata_encoding_version.iter().cloned()); - result.push((len >> 24) as u8); - result.push((len >> 16) as u8); - result.push((len >> 8) as u8); - result.push((len >> 0) as u8); - result.extend(v); + let meta_start = 8 + ::common::metadata_encoding_version.len(); + let len = meta_len - meta_start; + let mut result = cursor.into_inner(); + result[meta_start - 4] = (len >> 24) as u8; + result[meta_start - 3] = (len >> 16) as u8; + result[meta_start - 2] = (len >> 8) as u8; + result[meta_start - 1] = (len >> 0) as u8; result } -fn encode_metadata_inner(ecx: &mut EncodeContext, krate: &hir::Crate) { - struct Stats { - attr_bytes: u64, - dep_bytes: u64, - lang_item_bytes: u64, - native_lib_bytes: u64, - plugin_registrar_fn_bytes: u64, - codemap_bytes: u64, - macro_defs_bytes: u64, - impl_bytes: u64, - reachable_bytes: u64, - item_bytes: u64, - index_bytes: u64, - xref_bytes: u64, - zero_bytes: u64, - total_bytes: u64, - } - let mut stats = Stats { - attr_bytes: 0, - dep_bytes: 0, - lang_item_bytes: 0, - native_lib_bytes: 0, - plugin_registrar_fn_bytes: 0, - codemap_bytes: 0, - macro_defs_bytes: 0, - impl_bytes: 0, - reachable_bytes: 0, - item_bytes: 0, - index_bytes: 0, - xref_bytes: 0, - zero_bytes: 0, - total_bytes: 0, - }; - +fn encode_metadata_inner(ecx: &mut EncodeContext) { encode_rustc_version(ecx); let tcx = ecx.tcx; @@ -1804,89 +1825,92 @@ fn encode_metadata_inner(ecx: &mut EncodeContext, krate: &hir::Crate) { encode_dylib_dependency_formats(ecx); encode_panic_strategy(ecx); - let mut i = ecx.writer.seek(SeekFrom::Current(0)).unwrap(); + let krate = tcx.map.krate(); + + let mut i = ecx.position(); encode_attributes(ecx, &krate.attrs); - stats.attr_bytes = ecx.writer.seek(SeekFrom::Current(0)).unwrap() - i; + let attr_bytes = ecx.position() - i; - i = ecx.writer.seek(SeekFrom::Current(0)).unwrap(); + i = ecx.position(); encode_crate_deps(ecx, ecx.cstore); - stats.dep_bytes = ecx.writer.seek(SeekFrom::Current(0)).unwrap() - i; + let dep_bytes = ecx.position() - i; // Encode the language items. - i = ecx.writer.seek(SeekFrom::Current(0)).unwrap(); + i = ecx.position(); encode_lang_items(ecx); - stats.lang_item_bytes = ecx.writer.seek(SeekFrom::Current(0)).unwrap() - i; + let lang_item_bytes = ecx.position() - i; // Encode the native libraries used - i = ecx.writer.seek(SeekFrom::Current(0)).unwrap(); + i = ecx.position(); encode_native_libraries(ecx); - stats.native_lib_bytes = ecx.writer.seek(SeekFrom::Current(0)).unwrap() - i; + let native_lib_bytes = ecx.position() - i; // Encode the plugin registrar function - i = ecx.writer.seek(SeekFrom::Current(0)).unwrap(); + i = ecx.position(); encode_plugin_registrar_fn(ecx); - stats.plugin_registrar_fn_bytes = ecx.writer.seek(SeekFrom::Current(0)).unwrap() - i; + let plugin_registrar_fn_bytes = ecx.position() - i; // Encode codemap - i = ecx.writer.seek(SeekFrom::Current(0)).unwrap(); + i = ecx.position(); encode_codemap(ecx); - stats.codemap_bytes = ecx.writer.seek(SeekFrom::Current(0)).unwrap() - i; + let codemap_bytes = ecx.position() - i; // Encode macro definitions - i = ecx.writer.seek(SeekFrom::Current(0)).unwrap(); + i = ecx.position(); encode_macro_defs(ecx, krate); - stats.macro_defs_bytes = ecx.writer.seek(SeekFrom::Current(0)).unwrap() - i; + let macro_defs_bytes = ecx.position() - i; // Encode the def IDs of impls, for coherence checking. - i = ecx.writer.seek(SeekFrom::Current(0)).unwrap(); + i = ecx.position(); encode_impls(ecx, krate); - stats.impl_bytes = ecx.writer.seek(SeekFrom::Current(0)).unwrap() - i; + let impl_bytes = ecx.position() - i; // Encode reachability info. - i = ecx.writer.seek(SeekFrom::Current(0)).unwrap(); + i = ecx.position(); encode_reachable(ecx); - stats.reachable_bytes = ecx.writer.seek(SeekFrom::Current(0)).unwrap() - i; + let reachable_bytes = ecx.position() - i; // Encode and index the items. ecx.start_tag(tag_items); - i = ecx.writer.seek(SeekFrom::Current(0)).unwrap(); + i = ecx.position(); let (items, xrefs) = encode_info_for_items(ecx); - stats.item_bytes = ecx.writer.seek(SeekFrom::Current(0)).unwrap() - i; + let item_bytes = ecx.position() - i; ecx.end_tag(); - i = ecx.writer.seek(SeekFrom::Current(0)).unwrap(); + i = ecx.position(); encode_item_index(ecx, items); - stats.index_bytes = ecx.writer.seek(SeekFrom::Current(0)).unwrap() - i; + let index_bytes = ecx.position() - i; - i = ecx.writer.seek(SeekFrom::Current(0)).unwrap(); + i = ecx.position(); encode_xrefs(ecx, xrefs); - stats.xref_bytes = ecx.writer.seek(SeekFrom::Current(0)).unwrap() - i; + let xref_bytes = ecx.position() - i; encode_struct_field_attrs(ecx, krate); - stats.total_bytes = ecx.writer.seek(SeekFrom::Current(0)).unwrap(); + let total_bytes = ecx.position(); if ecx.tcx.sess.meta_stats() { - for e in ecx.writer.get_ref() { + let mut zero_bytes = 0; + for e in ecx.opaque.cursor.get_ref() { if *e == 0 { - stats.zero_bytes += 1; + zero_bytes += 1; } } println!("metadata stats:"); - println!(" attribute bytes: {}", stats.attr_bytes); - println!(" dep bytes: {}", stats.dep_bytes); - println!(" lang item bytes: {}", stats.lang_item_bytes); - println!(" native bytes: {}", stats.native_lib_bytes); - println!("plugin registrar bytes: {}", stats.plugin_registrar_fn_bytes); - println!(" codemap bytes: {}", stats.codemap_bytes); - println!(" macro def bytes: {}", stats.macro_defs_bytes); - println!(" impl bytes: {}", stats.impl_bytes); - println!(" reachable bytes: {}", stats.reachable_bytes); - println!(" item bytes: {}", stats.item_bytes); - println!(" index bytes: {}", stats.index_bytes); - println!(" xref bytes: {}", stats.xref_bytes); - println!(" zero bytes: {}", stats.zero_bytes); - println!(" total bytes: {}", stats.total_bytes); + println!(" attribute bytes: {}", attr_bytes); + println!(" dep bytes: {}", dep_bytes); + println!(" lang item bytes: {}", lang_item_bytes); + println!(" native bytes: {}", native_lib_bytes); + println!("plugin registrar bytes: {}", plugin_registrar_fn_bytes); + println!(" codemap bytes: {}", codemap_bytes); + println!(" macro def bytes: {}", macro_defs_bytes); + println!(" impl bytes: {}", impl_bytes); + println!(" reachable bytes: {}", reachable_bytes); + println!(" item bytes: {}", item_bytes); + println!(" index bytes: {}", index_bytes); + println!(" xref bytes: {}", xref_bytes); + println!(" zero bytes: {}", zero_bytes); + println!(" total bytes: {}", total_bytes); } } diff --git a/src/librustc_metadata/index.rs b/src/librustc_metadata/index.rs index b850073462f5a..63d7f1b58bb0d 100644 --- a/src/librustc_metadata/index.rs +++ b/src/librustc_metadata/index.rs @@ -73,15 +73,15 @@ impl IndexData { } } - pub fn record(&mut self, def_id: DefId, position: u64) { + pub fn record(&mut self, def_id: DefId, position: usize) { assert!(def_id.is_local()); self.record_index(def_id.index, position); } - pub fn record_index(&mut self, item: DefIndex, position: u64) { + pub fn record_index(&mut self, item: DefIndex, position: usize) { let item = item.as_usize(); - assert!(position < (u32::MAX as u64)); + assert!(position < (u32::MAX as usize)); let position = position as u32; assert!(self.positions[item] == u32::MAX, diff --git a/src/librustc_metadata/index_builder.rs b/src/librustc_metadata/index_builder.rs index de2f1c4fb0c85..fd25128575f1a 100644 --- a/src/librustc_metadata/index_builder.rs +++ b/src/librustc_metadata/index_builder.rs @@ -28,10 +28,9 @@ //! incremental compilation purposes. //! //! The `IndexBuilder` facilitates both of these. It is created -//! with an RBML encoder isntance (`rbml_w`) along with an -//! `EncodingContext` (`ecx`), which it encapsulates. It has one main -//! method, `record()`. You invoke `record` like so to create a new -//! `data_item` element in the list: +//! with an `EncodingContext` (`ecx`), which it encapsulates. +//! It has one main method, `record()`. You invoke `record` +//! like so to create a new `data_item` element in the list: //! //! ``` //! index.record(some_def_id, callback_fn, data) @@ -43,9 +42,9 @@ //! returns, the `common::data_item` tag will be closed. //! //! The `ItemContentBuilder` is another type that just offers access -//! to the `ecx` and `rbml_w` that were given in, as well as -//! maintaining a list of `xref` instances, which are used to extract -//! common data so it is not re-serialized. +//! to the `ecx` that was given in, as well as maintaining a list of +//! `xref` instances, which are used to extract common data so it is +//! not re-serialized. //! //! `ItemContentBuilder` is a distinct type which does not offer the //! `record` method, so that we can ensure that `common::data_item` elements diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs index 428b33f2bfa66..7205a88618fcc 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -51,9 +51,6 @@ extern crate rustc_const_math; extern crate test; pub mod rbml { - pub extern crate rbml as rbml_crate; - pub use self::rbml_crate::{Error, leb128, opaque}; - pub mod writer; pub mod reader; pub use self::reader::Doc; diff --git a/src/librustc_metadata/rbml/reader.rs b/src/librustc_metadata/rbml/reader.rs index d66ca38e6244d..9bbeb73ce3eca 100644 --- a/src/librustc_metadata/rbml/reader.rs +++ b/src/librustc_metadata/rbml/reader.rs @@ -45,87 +45,13 @@ //! **Data** can be either binary bytes or zero or more nested RBML documents. //! Nested documents cannot overflow, and should be entirely contained //! within a parent document. -//! -//! # Predefined Tags -//! -//! Most RBML tags are defined by the application. -//! (For the rust object metadata, see also `rustc::metadata::common`.) -//! RBML itself does define a set of predefined tags however, -//! intended for the auto-serialization implementation. -//! -//! Predefined tags with an implicit length: -//! -//! - `U8` (`00`): 1-byte unsigned integer. -//! - `U16` (`01`): 2-byte big endian unsigned integer. -//! - `U32` (`02`): 4-byte big endian unsigned integer. -//! - `U64` (`03`): 8-byte big endian unsigned integer. -//! Any of `U*` tags can be used to encode primitive unsigned integer types, -//! as long as it is no greater than the actual size. -//! For example, `u8` can only be represented via the `U8` tag. -//! -//! - `I8` (`04`): 1-byte signed integer. -//! - `I16` (`05`): 2-byte big endian signed integer. -//! - `I32` (`06`): 4-byte big endian signed integer. -//! - `I64` (`07`): 8-byte big endian signed integer. -//! Similar to `U*` tags. Always uses two's complement encoding. -//! -//! - `Bool` (`08`): 1-byte boolean value, `00` for false and `01` for true. -//! -//! - `Char` (`09`): 4-byte big endian Unicode scalar value. -//! Surrogate pairs or out-of-bound values are invalid. -//! -//! - `F32` (`0a`): 4-byte big endian unsigned integer representing -//! IEEE 754 binary32 floating-point format. -//! - `F64` (`0b`): 8-byte big endian unsigned integer representing -//! IEEE 754 binary64 floating-point format. -//! -//! - `Sub8` (`0c`): 1-byte unsigned integer for supplementary information. -//! - `Sub32` (`0d`): 4-byte unsigned integer for supplementary information. -//! Those two tags normally occur as the first subdocument of certain tags, -//! namely `Enum`, `Vec` and `Map`, to provide a variant or size information. -//! They can be used interchangeably. -//! -//! Predefined tags with an explicit length: -//! -//! - `Str` (`10`): A UTF-8-encoded string. -//! -//! - `Enum` (`11`): An enum. -//! The first subdocument should be `Sub*` tags with a variant ID. -//! Subsequent subdocuments, if any, encode variant arguments. -//! -//! - `Vec` (`12`): A vector (sequence). -//! - `VecElt` (`13`): A vector element. -//! The first subdocument should be `Sub*` tags with the number of elements. -//! Subsequent subdocuments should be `VecElt` tag per each element. -//! -//! - `Map` (`14`): A map (associated array). -//! - `MapKey` (`15`): A key part of the map entry. -//! - `MapVal` (`16`): A value part of the map entry. -//! The first subdocument should be `Sub*` tags with the number of entries. -//! Subsequent subdocuments should be an alternating sequence of -//! `MapKey` and `MapVal` tags per each entry. -//! -//! - `Opaque` (`17`): An opaque, custom-format tag. -//! Used to wrap ordinary custom tags or data in the auto-serialized context. -//! Rustc typically uses this to encode type information. -//! -//! First 0x20 tags are reserved by RBML; custom tags start at 0x20. #[cfg(test)] use test::Bencher; -pub use self::EbmlEncoderTag::*; - -use std::char; -use std::isize; -use std::mem::transmute; +use std::fmt; use std::str; -use rustc_serialize as serialize; - -use rbml::Error; -use rbml::Error::*; - #[derive(Clone, Copy)] pub struct Doc<'a> { pub data: &'a [u8], @@ -142,6 +68,17 @@ impl<'doc> Doc<'doc> { } } + pub fn at(data: &'doc [u8], start: usize) -> Doc<'doc> { + let elt_tag = tag_at(data, start).unwrap(); + let elt_size = tag_len_at(data, elt_tag.next).unwrap(); + let end = elt_size.next + elt_size.val; + Doc { + data: data, + start: elt_size.next, + end: end, + } + } + pub fn get(&self, tag: usize) -> Doc<'doc> { get_doc(*self, tag) } @@ -159,54 +96,19 @@ impl<'doc> Doc<'doc> { } } -pub struct TaggedDoc<'a> { - tag: usize, - pub doc: Doc<'a>, +#[derive(Debug)] +pub enum Error { + IntTooBig(usize), + InvalidTag(usize) } -pub type DecodeResult = Result; - -#[derive(Copy, Clone, Debug)] -pub enum EbmlEncoderTag { - // tags 00..1f are reserved for auto-serialization. - // first NUM_IMPLICIT_TAGS tags are implicitly sized and lengths are not encoded. - EsU8 = 0x00, // + 1 byte - EsU16 = 0x01, // + 2 bytes - EsU32 = 0x02, // + 4 bytes - EsU64 = 0x03, // + 8 bytes - EsI8 = 0x04, // + 1 byte - EsI16 = 0x05, // + 2 bytes - EsI32 = 0x06, // + 4 bytes - EsI64 = 0x07, // + 8 bytes - EsBool = 0x08, // + 1 byte - EsChar = 0x09, // + 4 bytes - EsF32 = 0x0a, // + 4 bytes - EsF64 = 0x0b, // + 8 bytes - EsSub8 = 0x0c, // + 1 byte - EsSub32 = 0x0d, // + 4 bytes - // 0x0e and 0x0f are reserved - EsStr = 0x10, - EsEnum = 0x11, // encodes the variant id as the first EsSub* - EsVec = 0x12, // encodes the # of elements as the first EsSub* - EsVecElt = 0x13, - EsMap = 0x14, // encodes the # of pairs as the first EsSub* - EsMapKey = 0x15, - EsMapVal = 0x16, - EsOpaque = 0x17, +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + // FIXME: this should be a more useful display form + fmt::Debug::fmt(self, f) + } } -pub const NUM_IMPLICIT_TAGS: usize = 0x0e; - -#[cfg_attr(rustfmt, rustfmt_skip)] -static TAG_IMPLICIT_LEN: [i8; NUM_IMPLICIT_TAGS] = [ - 1, 2, 4, 8, // EsU* - 1, 2, 4, 8, // ESI* - 1, // EsBool - 4, // EsChar - 4, 8, // EsF* - 1, 4, // EsSub* -]; - // rbml reading macro_rules! try_or { @@ -227,7 +129,7 @@ pub struct Res { pub next: usize, } -pub fn tag_at(data: &[u8], start: usize) -> DecodeResult { +pub fn tag_at(data: &[u8], start: usize) -> Result { let v = data[start] as usize; if v < 0xf0 { Ok(Res { @@ -241,12 +143,12 @@ pub fn tag_at(data: &[u8], start: usize) -> DecodeResult { }) } else { // every tag starting with byte 0xf0 is an overlong form, which is prohibited. - Err(InvalidTag(v)) + Err(Error::InvalidTag(v)) } } #[inline(never)] -fn vuint_at_slow(data: &[u8], start: usize) -> DecodeResult { +fn vuint_at_slow(data: &[u8], start: usize) -> Result { let a = data[start]; if a & 0x80 != 0 { return Ok(Res { @@ -275,10 +177,10 @@ fn vuint_at_slow(data: &[u8], start: usize) -> DecodeResult { next: start + 4, }); } - Err(IntTooBig(a as usize)) + Err(Error::IntTooBig(a as usize)) } -pub fn vuint_at(data: &[u8], start: usize) -> DecodeResult { +pub fn vuint_at(data: &[u8], start: usize) -> Result { if data.len() - start < 4 { return vuint_at_slow(data, start); } @@ -332,36 +234,15 @@ pub fn vuint_at(data: &[u8], start: usize) -> DecodeResult { } } -pub fn tag_len_at(data: &[u8], tag: Res) -> DecodeResult { - if tag.val < NUM_IMPLICIT_TAGS && TAG_IMPLICIT_LEN[tag.val] >= 0 { - Ok(Res { - val: TAG_IMPLICIT_LEN[tag.val] as usize, - next: tag.next, - }) - } else { - vuint_at(data, tag.next) - } -} - -pub fn doc_at<'a>(data: &'a [u8], start: usize) -> DecodeResult> { - let elt_tag = tag_at(data, start)?; - let elt_size = tag_len_at(data, elt_tag)?; - let end = elt_size.next + elt_size.val; - Ok(TaggedDoc { - tag: elt_tag.val, - doc: Doc { - data: data, - start: elt_size.next, - end: end, - }, - }) +pub fn tag_len_at(data: &[u8], next: usize) -> Result { + vuint_at(data, next) } pub fn maybe_get_doc<'a>(d: Doc<'a>, tg: usize) -> Option> { let mut pos = d.start; while pos < d.end { let elt_tag = try_or!(tag_at(d.data, pos), None); - let elt_size = try_or!(tag_len_at(d.data, elt_tag), None); + let elt_size = try_or!(tag_len_at(d.data, elt_tag.next), None); pos = elt_size.next + elt_size.val; if elt_tag.val == tg { return Some(Doc { @@ -378,8 +259,7 @@ pub fn get_doc<'a>(d: Doc<'a>, tg: usize) -> Doc<'a> { match maybe_get_doc(d, tg) { Some(d) => d, None => { - error!("failed to find block with tag {:?}", tg); - panic!(); + bug!("failed to find block with tag {:?}", tg); } } } @@ -404,7 +284,7 @@ impl<'a> Iterator for DocsIterator<'a> { self.d.start = self.d.end; None }); - let elt_size = try_or!(tag_len_at(self.d.data, elt_tag), { + let elt_size = try_or!(tag_len_at(self.d.data, elt_tag.next), { self.d.start = self.d.end; None }); @@ -509,419 +389,6 @@ pub fn doc_as_i64(d: Doc) -> i64 { doc_as_u64(d) as i64 } -pub struct Decoder<'a> { - parent: Doc<'a>, - pos: usize, -} - -impl<'doc> Decoder<'doc> { - pub fn new(d: Doc<'doc>) -> Decoder<'doc> { - Decoder { - parent: d, - pos: d.start, - } - } - - fn next_doc(&mut self, exp_tag: EbmlEncoderTag) -> DecodeResult> { - debug!(". next_doc(exp_tag={:?})", exp_tag); - if self.pos >= self.parent.end { - return Err(Expected(format!("no more documents in current node!"))); - } - let TaggedDoc { tag: r_tag, doc: r_doc } = doc_at(self.parent.data, self.pos)?; - debug!("self.parent={:?}-{:?} self.pos={:?} r_tag={:?} r_doc={:?}-{:?}", - self.parent.start, - self.parent.end, - self.pos, - r_tag, - r_doc.start, - r_doc.end); - if r_tag != (exp_tag as usize) { - return Err(Expected(format!("expected EBML doc with tag {:?} but found tag {:?}", - exp_tag, - r_tag))); - } - if r_doc.end > self.parent.end { - return Err(Expected(format!("invalid EBML, child extends to {:#x}, parent to \ - {:#x}", - r_doc.end, - self.parent.end))); - } - self.pos = r_doc.end; - Ok(r_doc) - } - - fn _next_sub(&mut self) -> DecodeResult { - // empty vector/map optimization - if self.parent.is_empty() { - return Ok(0); - } - - let TaggedDoc { tag: r_tag, doc: r_doc } = doc_at(self.parent.data, self.pos)?; - let r = if r_tag == (EsSub8 as usize) { - doc_as_u8(r_doc) as usize - } else if r_tag == (EsSub32 as usize) { - doc_as_u32(r_doc) as usize - } else { - return Err(Expected(format!("expected EBML doc with tag {:?} or {:?} but found \ - tag {:?}", - EsSub8, - EsSub32, - r_tag))); - }; - if r_doc.end > self.parent.end { - return Err(Expected(format!("invalid EBML, child extends to {:#x}, parent to \ - {:#x}", - r_doc.end, - self.parent.end))); - } - self.pos = r_doc.end; - debug!("_next_sub result={:?}", r); - Ok(r) - } - - // variable-length unsigned integer with different tags. - // `last_tag` should be the largest allowed unsigned integer tag. - // all tags between them should be valid, in the order of u8, u16, u32 and u64. - fn next_uint(&mut self, - last_tag: EbmlEncoderTag) - -> DecodeResult { - if self.pos >= self.parent.end { - return Err(Expected(format!("no more documents in current node!"))); - } - - let TaggedDoc { tag: r_tag, doc: r_doc } = doc_at(self.parent.data, self.pos)?; - let r = if EsU8 as usize <= r_tag && r_tag <= last_tag as usize { - match r_tag - EsU8 as usize { - 0 => doc_as_u8(r_doc) as u64, - 1 => doc_as_u16(r_doc) as u64, - 2 => doc_as_u32(r_doc) as u64, - 3 => doc_as_u64(r_doc), - _ => unreachable!(), - } - } else { - return Err(Expected(format!("expected EBML doc with tag EsU8 through {:?} but \ - found tag {:?}", - last_tag, - r_tag))); - }; - if r_doc.end > self.parent.end { - return Err(Expected(format!("invalid EBML, child extends to {:#x}, parent to \ - {:#x}", - r_doc.end, - self.parent.end))); - } - self.pos = r_doc.end; - debug!("next_uint({:?}) result={:?}", last_tag, r); - Ok(r) - } - - // variable-length signed integer with different tags. - // `last_tag` should be the largest allowed signed integer tag. - // all tags between them should be valid, in the order of i8, i16, i32 and i64. - fn next_int(&mut self, - last_tag: EbmlEncoderTag) - -> DecodeResult { - if self.pos >= self.parent.end { - return Err(Expected(format!("no more documents in current node!"))); - } - - let TaggedDoc { tag: r_tag, doc: r_doc } = doc_at(self.parent.data, self.pos)?; - let r = if EsI8 as usize <= r_tag && r_tag <= last_tag as usize { - match r_tag - EsI8 as usize { - 0 => doc_as_i8(r_doc) as i64, - 1 => doc_as_i16(r_doc) as i64, - 2 => doc_as_i32(r_doc) as i64, - 3 => doc_as_i64(r_doc), - _ => unreachable!(), - } - } else { - return Err(Expected(format!("expected EBML doc with tag EsI8 through {:?} but \ - found tag {:?}", - last_tag, - r_tag))); - }; - if r_doc.end > self.parent.end { - return Err(Expected(format!("invalid EBML, child extends to {:#x}, parent to \ - {:#x}", - r_doc.end, - self.parent.end))); - } - self.pos = r_doc.end; - debug!("next_int({:?}) result={:?}", last_tag, r); - Ok(r) - } - - pub fn position(&self) -> usize { - self.pos - } - - pub fn advance(&mut self, bytes: usize) { - self.pos += bytes; - } -} - -impl<'doc, 'tcx> ::decoder::DecodeContext<'doc, 'tcx> { - pub fn read_opaque(&mut self, op: F) -> DecodeResult - where F: FnOnce(&mut Self, Doc) -> DecodeResult - { - let doc = self.next_doc(EsOpaque)?; - op(self, doc) - } - - fn push_doc(&mut self, exp_tag: EbmlEncoderTag, f: F) -> DecodeResult - where F: FnOnce(&mut Self) -> DecodeResult - { - let d = self.next_doc(exp_tag)?; - let old_parent = self.parent; - let old_pos = self.pos; - self.parent = d; - self.pos = d.start; - let r = f(self)?; - self.parent = old_parent; - self.pos = old_pos; - Ok(r) - } -} - -impl<'doc, 'tcx> serialize::Decoder for ::decoder::DecodeContext<'doc, 'tcx> { - type Error = Error; - fn read_nil(&mut self) -> DecodeResult<()> { - Ok(()) - } - - fn read_u64(&mut self) -> DecodeResult { - self.next_uint(EsU64) - } - fn read_u32(&mut self) -> DecodeResult { - Ok(self.next_uint(EsU32)? as u32) - } - fn read_u16(&mut self) -> DecodeResult { - Ok(self.next_uint(EsU16)? as u16) - } - fn read_u8(&mut self) -> DecodeResult { - Ok(doc_as_u8(self.next_doc(EsU8)?)) - } - fn read_usize(&mut self) -> DecodeResult { - let v = self.read_u64()?; - if v > (::std::usize::MAX as u64) { - Err(IntTooBig(v as usize)) - } else { - Ok(v as usize) - } - } - - fn read_i64(&mut self) -> DecodeResult { - Ok(self.next_int(EsI64)? as i64) - } - fn read_i32(&mut self) -> DecodeResult { - Ok(self.next_int(EsI32)? as i32) - } - fn read_i16(&mut self) -> DecodeResult { - Ok(self.next_int(EsI16)? as i16) - } - fn read_i8(&mut self) -> DecodeResult { - Ok(doc_as_u8(self.next_doc(EsI8)?) as i8) - } - fn read_isize(&mut self) -> DecodeResult { - let v = self.next_int(EsI64)? as i64; - if v > (isize::MAX as i64) || v < (isize::MIN as i64) { - debug!("FIXME \\#6122: Removing this makes this function miscompile"); - Err(IntTooBig(v as usize)) - } else { - Ok(v as isize) - } - } - - fn read_bool(&mut self) -> DecodeResult { - Ok(doc_as_u8(self.next_doc(EsBool)?) != 0) - } - - fn read_f64(&mut self) -> DecodeResult { - let bits = doc_as_u64(self.next_doc(EsF64)?); - Ok(unsafe { transmute(bits) }) - } - fn read_f32(&mut self) -> DecodeResult { - let bits = doc_as_u32(self.next_doc(EsF32)?); - Ok(unsafe { transmute(bits) }) - } - fn read_char(&mut self) -> DecodeResult { - Ok(char::from_u32(doc_as_u32(self.next_doc(EsChar)?)).unwrap()) - } - fn read_str(&mut self) -> DecodeResult { - Ok(self.next_doc(EsStr)?.to_string()) - } - - // Compound types: - fn read_enum(&mut self, name: &str, f: F) -> DecodeResult - where F: FnOnce(&mut Self) -> DecodeResult - { - debug!("read_enum({})", name); - - let doc = self.next_doc(EsEnum)?; - - let (old_parent, old_pos) = (self.parent, self.pos); - self.parent = doc; - self.pos = self.parent.start; - - let result = f(self)?; - - self.parent = old_parent; - self.pos = old_pos; - Ok(result) - } - - fn read_enum_variant(&mut self, _: &[&str], mut f: F) -> DecodeResult - where F: FnMut(&mut Self, usize) -> DecodeResult - { - debug!("read_enum_variant()"); - let idx = self._next_sub()?; - debug!(" idx={}", idx); - - f(self, idx) - } - - fn read_enum_variant_arg(&mut self, idx: usize, f: F) -> DecodeResult - where F: FnOnce(&mut Self) -> DecodeResult - { - debug!("read_enum_variant_arg(idx={})", idx); - f(self) - } - - fn read_enum_struct_variant(&mut self, _: &[&str], mut f: F) -> DecodeResult - where F: FnMut(&mut Self, usize) -> DecodeResult - { - debug!("read_enum_struct_variant()"); - let idx = self._next_sub()?; - debug!(" idx={}", idx); - - f(self, idx) - } - - fn read_enum_struct_variant_field(&mut self, - name: &str, - idx: usize, - f: F) - -> DecodeResult - where F: FnOnce(&mut Self) -> DecodeResult - { - debug!("read_enum_struct_variant_arg(name={}, idx={})", name, idx); - f(self) - } - - fn read_struct(&mut self, name: &str, _: usize, f: F) -> DecodeResult - where F: FnOnce(&mut Self) -> DecodeResult - { - debug!("read_struct(name={})", name); - f(self) - } - - fn read_struct_field(&mut self, name: &str, idx: usize, f: F) -> DecodeResult - where F: FnOnce(&mut Self) -> DecodeResult - { - debug!("read_struct_field(name={}, idx={})", name, idx); - f(self) - } - - fn read_tuple(&mut self, tuple_len: usize, f: F) -> DecodeResult - where F: FnOnce(&mut Self) -> DecodeResult - { - debug!("read_tuple()"); - self.read_seq(move |d, len| { - if len == tuple_len { - f(d) - } else { - Err(Expected(format!("Expected tuple of length `{}`, found tuple of length \ - `{}`", - tuple_len, - len))) - } - }) - } - - fn read_tuple_arg(&mut self, idx: usize, f: F) -> DecodeResult - where F: FnOnce(&mut Self) -> DecodeResult - { - debug!("read_tuple_arg(idx={})", idx); - self.read_seq_elt(idx, f) - } - - fn read_tuple_struct(&mut self, name: &str, len: usize, f: F) -> DecodeResult - where F: FnOnce(&mut Self) -> DecodeResult - { - debug!("read_tuple_struct(name={})", name); - self.read_tuple(len, f) - } - - fn read_tuple_struct_arg(&mut self, idx: usize, f: F) -> DecodeResult - where F: FnOnce(&mut Self) -> DecodeResult - { - debug!("read_tuple_struct_arg(idx={})", idx); - self.read_tuple_arg(idx, f) - } - - fn read_option(&mut self, mut f: F) -> DecodeResult - where F: FnMut(&mut Self, bool) -> DecodeResult - { - debug!("read_option()"); - self.read_enum("Option", move |this| { - this.read_enum_variant(&["None", "Some"], move |this, idx| { - match idx { - 0 => f(this, false), - 1 => f(this, true), - _ => Err(Expected(format!("Expected None or Some"))), - } - }) - }) - } - - fn read_seq(&mut self, f: F) -> DecodeResult - where F: FnOnce(&mut Self, usize) -> DecodeResult - { - debug!("read_seq()"); - self.push_doc(EsVec, move |d| { - let len = d._next_sub()?; - debug!(" len={}", len); - f(d, len) - }) - } - - fn read_seq_elt(&mut self, idx: usize, f: F) -> DecodeResult - where F: FnOnce(&mut Self) -> DecodeResult - { - debug!("read_seq_elt(idx={})", idx); - self.push_doc(EsVecElt, f) - } - - fn read_map(&mut self, f: F) -> DecodeResult - where F: FnOnce(&mut Self, usize) -> DecodeResult - { - debug!("read_map()"); - self.push_doc(EsMap, move |d| { - let len = d._next_sub()?; - debug!(" len={}", len); - f(d, len) - }) - } - - fn read_map_elt_key(&mut self, idx: usize, f: F) -> DecodeResult - where F: FnOnce(&mut Self) -> DecodeResult - { - debug!("read_map_elt_key(idx={})", idx); - self.push_doc(EsMapKey, f) - } - - fn read_map_elt_val(&mut self, idx: usize, f: F) -> DecodeResult - where F: FnOnce(&mut Self) -> DecodeResult - { - debug!("read_map_elt_val(idx={})", idx); - self.push_doc(EsMapVal, f) - } - - fn error(&mut self, err: &str) -> Error { - ApplicationError(err.to_string()) - } -} - #[test] fn test_vuint_at() { let data = &[ diff --git a/src/librustc_metadata/rbml/writer.rs b/src/librustc_metadata/rbml/writer.rs index f22a9d1cd003e..94e9b394f1f90 100644 --- a/src/librustc_metadata/rbml/writer.rs +++ b/src/librustc_metadata/rbml/writer.rs @@ -12,19 +12,15 @@ use std::mem; use std::io::prelude::*; use std::io::{self, SeekFrom, Cursor}; -use rbml::opaque; -use rbml::reader::EbmlEncoderTag::*; -use rbml::reader::NUM_IMPLICIT_TAGS; - -use rustc_serialize as serialize; +use rustc_serialize::opaque; pub type EncodeResult = io::Result<()>; // rbml writing -pub struct Encoder { - pub writer: Cursor>, - size_positions: Vec, - relax_limit: u64, // do not move encoded bytes before this position +pub struct Encoder<'a> { + pub opaque: opaque::Encoder<'a>, + size_positions: Vec, + relax_limit: usize, // do not move encoded bytes before this position } const NUM_TAGS: usize = 0x1000; @@ -65,10 +61,10 @@ pub fn write_vuint(w: &mut W, n: usize) -> EncodeResult { Err(io::Error::new(io::ErrorKind::Other, &format!("isize too big: {}", n)[..])) } -impl Encoder { - pub fn new() -> Encoder { +impl<'a> Encoder<'a> { + pub fn new(cursor: &'a mut Cursor>) -> Encoder<'a> { Encoder { - writer: Cursor::new(vec![]), + opaque: opaque::Encoder::new(cursor), size_positions: vec![], relax_limit: 0, } @@ -76,23 +72,21 @@ impl Encoder { pub fn start_tag(&mut self, tag_id: usize) -> EncodeResult { debug!("Start tag {:?}", tag_id); - assert!(tag_id >= NUM_IMPLICIT_TAGS); // Write the enum ID: - write_tag(&mut self.writer, tag_id)?; + write_tag(&mut self.opaque.cursor, tag_id)?; // Write a placeholder four-byte size. - let cur_pos = self.writer.seek(SeekFrom::Current(0))?; + let cur_pos = self.position(); self.size_positions.push(cur_pos); - let zeroes: &[u8] = &[0, 0, 0, 0]; - self.writer.write_all(zeroes) + self.opaque.cursor.write_all(&[0, 0, 0, 0]) } pub fn end_tag(&mut self) -> EncodeResult { let last_size_pos = self.size_positions.pop().unwrap(); - let cur_pos = self.writer.seek(SeekFrom::Current(0))?; - self.writer.seek(SeekFrom::Start(last_size_pos))?; - let size = (cur_pos - last_size_pos - 4) as usize; + let cur_pos = self.position(); + self.opaque.cursor.seek(SeekFrom::Start(last_size_pos as u64))?; + let size = cur_pos - last_size_pos - 4; // relax the size encoding for small tags (bigger tags are costly to move). // we should never try to move the stable positions, however. @@ -101,18 +95,17 @@ impl Encoder { // we can't alter the buffer in place, so have a temporary buffer let mut buf = [0u8; RELAX_MAX_SIZE]; { - let last_size_pos = last_size_pos as usize; - let data = &self.writer.get_ref()[last_size_pos + 4..cur_pos as usize]; + let data = &self.opaque.cursor.get_ref()[last_size_pos + 4..cur_pos]; buf[..size].copy_from_slice(data); } // overwrite the size and data and continue - write_vuint(&mut self.writer, size)?; - self.writer.write_all(&buf[..size])?; + write_vuint(&mut self.opaque.cursor, size)?; + self.opaque.cursor.write_all(&buf[..size])?; } else { // overwrite the size with an overlong encoding and skip past the data - write_sized_vuint(&mut self.writer, size, 4)?; - self.writer.seek(SeekFrom::Start(cur_pos))?; + write_sized_vuint(&mut self.opaque.cursor, size, 4)?; + self.opaque.cursor.seek(SeekFrom::Start(cur_pos as u64))?; } debug!("End tag (size = {:?})", size); @@ -128,10 +121,9 @@ impl Encoder { } pub fn wr_tagged_bytes(&mut self, tag_id: usize, b: &[u8]) -> EncodeResult { - assert!(tag_id >= NUM_IMPLICIT_TAGS); - write_tag(&mut self.writer, tag_id)?; - write_vuint(&mut self.writer, b.len())?; - self.writer.write_all(b) + write_tag(&mut self.opaque.cursor, tag_id)?; + write_vuint(&mut self.opaque.cursor, b.len())?; + self.opaque.cursor.write_all(b) } pub fn wr_tagged_u64(&mut self, tag_id: usize, v: u64) -> EncodeResult { @@ -147,344 +139,37 @@ impl Encoder { self.wr_tagged_u64(tag_id, v as u64) } - #[inline] - pub fn wr_tagged_u16(&mut self, tag_id: usize, v: u16) -> EncodeResult { - self.wr_tagged_u64(tag_id, v as u64) - } - #[inline] pub fn wr_tagged_u8(&mut self, tag_id: usize, v: u8) -> EncodeResult { self.wr_tagged_bytes(tag_id, &[v]) } - #[inline] - pub fn wr_tagged_i64(&mut self, tag_id: usize, v: i64) -> EncodeResult { - self.wr_tagged_u64(tag_id, v as u64) - } - - #[inline] - pub fn wr_tagged_i32(&mut self, tag_id: usize, v: i32) -> EncodeResult { - self.wr_tagged_u32(tag_id, v as u32) - } - - #[inline] - pub fn wr_tagged_i16(&mut self, tag_id: usize, v: i16) -> EncodeResult { - self.wr_tagged_u16(tag_id, v as u16) - } - - #[inline] - pub fn wr_tagged_i8(&mut self, tag_id: usize, v: i8) -> EncodeResult { - self.wr_tagged_bytes(tag_id, &[v as u8]) - } - pub fn wr_tagged_str(&mut self, tag_id: usize, v: &str) -> EncodeResult { self.wr_tagged_bytes(tag_id, v.as_bytes()) } - // for auto-serialization - fn wr_tagged_raw_bytes(&mut self, tag_id: usize, b: &[u8]) -> EncodeResult { - write_tag(&mut self.writer, tag_id)?; - self.writer.write_all(b) - } - - fn wr_tagged_raw_u64(&mut self, tag_id: usize, v: u64) -> EncodeResult { - let bytes: [u8; 8] = unsafe { mem::transmute(v.to_be()) }; - self.wr_tagged_raw_bytes(tag_id, &bytes) - } - - fn wr_tagged_raw_u32(&mut self, tag_id: usize, v: u32) -> EncodeResult { - let bytes: [u8; 4] = unsafe { mem::transmute(v.to_be()) }; - self.wr_tagged_raw_bytes(tag_id, &bytes) - } - - fn wr_tagged_raw_u16(&mut self, tag_id: usize, v: u16) -> EncodeResult { - let bytes: [u8; 2] = unsafe { mem::transmute(v.to_be()) }; - self.wr_tagged_raw_bytes(tag_id, &bytes) - } - - fn wr_tagged_raw_u8(&mut self, tag_id: usize, v: u8) -> EncodeResult { - self.wr_tagged_raw_bytes(tag_id, &[v]) - } - - fn wr_tagged_raw_i64(&mut self, tag_id: usize, v: i64) -> EncodeResult { - self.wr_tagged_raw_u64(tag_id, v as u64) - } - - fn wr_tagged_raw_i32(&mut self, tag_id: usize, v: i32) -> EncodeResult { - self.wr_tagged_raw_u32(tag_id, v as u32) - } - - fn wr_tagged_raw_i16(&mut self, tag_id: usize, v: i16) -> EncodeResult { - self.wr_tagged_raw_u16(tag_id, v as u16) - } - - fn wr_tagged_raw_i8(&mut self, tag_id: usize, v: i8) -> EncodeResult { - self.wr_tagged_raw_bytes(tag_id, &[v as u8]) - } - pub fn wr_bytes(&mut self, b: &[u8]) -> EncodeResult { debug!("Write {:?} bytes", b.len()); - self.writer.write_all(b) + self.opaque.cursor.write_all(b) } pub fn wr_str(&mut self, s: &str) -> EncodeResult { debug!("Write str: {:?}", s); - self.writer.write_all(s.as_bytes()) + self.opaque.cursor.write_all(s.as_bytes()) + } + + pub fn position(&mut self) -> usize { + self.opaque.position() as usize } /// Returns the current position while marking it stable, i.e. /// generated bytes so far wouldn't be affected by relaxation. - pub fn mark_stable_position(&mut self) -> u64 { - let pos = self.writer.seek(SeekFrom::Current(0)).unwrap(); + pub fn mark_stable_position(&mut self) -> usize { + let pos = self.position(); if self.relax_limit < pos { self.relax_limit = pos; } - pos - } - - // used internally to emit things like the vector length and so on - fn _emit_tagged_sub(&mut self, v: usize) -> EncodeResult { - if v as u8 as usize == v { - self.wr_tagged_raw_u8(EsSub8 as usize, v as u8) - } else if v as u32 as usize == v { - self.wr_tagged_raw_u32(EsSub32 as usize, v as u32) - } else { - Err(io::Error::new(io::ErrorKind::Other, - &format!("length or variant id too big: {}", v)[..])) - } - } - - pub fn emit_opaque(&mut self, f: F) -> EncodeResult - where F: FnOnce(&mut opaque::Encoder) -> EncodeResult - { - self.start_tag(EsOpaque as usize)?; - f(&mut opaque::Encoder::new(&mut self.writer))?; - self.mark_stable_position(); - self.end_tag() - } -} - -impl<'a, 'tcx> serialize::Encoder for ::encoder::EncodeContext<'a, 'tcx> { - type Error = io::Error; - - fn emit_nil(&mut self) -> EncodeResult { - Ok(()) - } - - fn emit_usize(&mut self, v: usize) -> EncodeResult { - self.emit_u64(v as u64) - } - fn emit_u64(&mut self, v: u64) -> EncodeResult { - if v as u32 as u64 == v { - self.emit_u32(v as u32) - } else { - self.wr_tagged_raw_u64(EsU64 as usize, v) - } - } - fn emit_u32(&mut self, v: u32) -> EncodeResult { - if v as u16 as u32 == v { - self.emit_u16(v as u16) - } else { - self.wr_tagged_raw_u32(EsU32 as usize, v) - } - } - fn emit_u16(&mut self, v: u16) -> EncodeResult { - if v as u8 as u16 == v { - self.emit_u8(v as u8) - } else { - self.wr_tagged_raw_u16(EsU16 as usize, v) - } - } - fn emit_u8(&mut self, v: u8) -> EncodeResult { - self.wr_tagged_raw_u8(EsU8 as usize, v) - } - - fn emit_isize(&mut self, v: isize) -> EncodeResult { - self.emit_i64(v as i64) - } - fn emit_i64(&mut self, v: i64) -> EncodeResult { - if v as i32 as i64 == v { - self.emit_i32(v as i32) - } else { - self.wr_tagged_raw_i64(EsI64 as usize, v) - } - } - fn emit_i32(&mut self, v: i32) -> EncodeResult { - if v as i16 as i32 == v { - self.emit_i16(v as i16) - } else { - self.wr_tagged_raw_i32(EsI32 as usize, v) - } - } - fn emit_i16(&mut self, v: i16) -> EncodeResult { - if v as i8 as i16 == v { - self.emit_i8(v as i8) - } else { - self.wr_tagged_raw_i16(EsI16 as usize, v) - } - } - fn emit_i8(&mut self, v: i8) -> EncodeResult { - self.wr_tagged_raw_i8(EsI8 as usize, v) - } - - fn emit_bool(&mut self, v: bool) -> EncodeResult { - self.wr_tagged_raw_u8(EsBool as usize, v as u8) - } - - fn emit_f64(&mut self, v: f64) -> EncodeResult { - let bits = unsafe { mem::transmute(v) }; - self.wr_tagged_raw_u64(EsF64 as usize, bits) - } - fn emit_f32(&mut self, v: f32) -> EncodeResult { - let bits = unsafe { mem::transmute(v) }; - self.wr_tagged_raw_u32(EsF32 as usize, bits) - } - fn emit_char(&mut self, v: char) -> EncodeResult { - self.wr_tagged_raw_u32(EsChar as usize, v as u32) - } - - fn emit_str(&mut self, v: &str) -> EncodeResult { - self.wr_tagged_str(EsStr as usize, v) - } - - fn emit_enum(&mut self, _name: &str, f: F) -> EncodeResult - where F: FnOnce(&mut Self) -> EncodeResult - { - self.start_tag(EsEnum as usize)?; - f(self)?; - self.end_tag() - } - - fn emit_enum_variant(&mut self, _: &str, v_id: usize, _: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Self) -> EncodeResult - { - self._emit_tagged_sub(v_id)?; - f(self) - } - - fn emit_enum_variant_arg(&mut self, _: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Self) -> EncodeResult - { - f(self) - } - - fn emit_enum_struct_variant(&mut self, - v_name: &str, - v_id: usize, - cnt: usize, - f: F) - -> EncodeResult - where F: FnOnce(&mut Self) -> EncodeResult - { - self.emit_enum_variant(v_name, v_id, cnt, f) - } - - fn emit_enum_struct_variant_field(&mut self, _: &str, idx: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Self) -> EncodeResult - { - self.emit_enum_variant_arg(idx, f) - } - - fn emit_struct(&mut self, _: &str, _len: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Self) -> EncodeResult - { - f(self) - } - - fn emit_struct_field(&mut self, _name: &str, _: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Self) -> EncodeResult - { - f(self) - } - - fn emit_tuple(&mut self, len: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Self) -> EncodeResult - { - self.emit_seq(len, f) - } - fn emit_tuple_arg(&mut self, idx: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Self) -> EncodeResult - { - self.emit_seq_elt(idx, f) - } - - fn emit_tuple_struct(&mut self, _: &str, len: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Self) -> EncodeResult - { - self.emit_seq(len, f) - } - fn emit_tuple_struct_arg(&mut self, idx: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Self) -> EncodeResult - { - self.emit_seq_elt(idx, f) - } - - fn emit_option(&mut self, f: F) -> EncodeResult - where F: FnOnce(&mut Self) -> EncodeResult - { - self.emit_enum("Option", f) - } - fn emit_option_none(&mut self) -> EncodeResult { - self.emit_enum_variant("None", 0, 0, |_| Ok(())) - } - fn emit_option_some(&mut self, f: F) -> EncodeResult - where F: FnOnce(&mut Self) -> EncodeResult - { - - self.emit_enum_variant("Some", 1, 1, f) - } - - fn emit_seq(&mut self, len: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Self) -> EncodeResult - { - if len == 0 { - // empty vector optimization - return self.wr_tagged_bytes(EsVec as usize, &[]); - } - - self.start_tag(EsVec as usize)?; - self._emit_tagged_sub(len)?; - f(self)?; - self.end_tag() - } - - fn emit_seq_elt(&mut self, _idx: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Self) -> EncodeResult - { - - self.start_tag(EsVecElt as usize)?; - f(self)?; - self.end_tag() - } - - fn emit_map(&mut self, len: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Self) -> EncodeResult - { - if len == 0 { - // empty map optimization - return self.wr_tagged_bytes(EsMap as usize, &[]); - } - - self.start_tag(EsMap as usize)?; - self._emit_tagged_sub(len)?; - f(self)?; - self.end_tag() - } - - fn emit_map_elt_key(&mut self, _idx: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Self) -> EncodeResult - { - - self.start_tag(EsMapKey as usize)?; - f(self)?; - self.end_tag() - } - - fn emit_map_elt_val(&mut self, _idx: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Self) -> EncodeResult - { - self.start_tag(EsMapVal as usize)?; - f(self)?; - self.end_tag() + let meta_start = 8 + ::common::metadata_encoding_version.len(); + pos - meta_start } } diff --git a/src/librustc_metadata/tydecode.rs b/src/librustc_metadata/tydecode.rs index 6d3b8571d3c3b..28e7b8852b300 100644 --- a/src/librustc_metadata/tydecode.rs +++ b/src/librustc_metadata/tydecode.rs @@ -24,7 +24,7 @@ use rustc::ty::subst::{Kind, Substs}; use rustc::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable}; use rbml; -use rbml::leb128; +use rustc_serialize::leb128; use std::str; use syntax::abi; use syntax::ast; diff --git a/src/librustc_metadata/tyencode.rs b/src/librustc_metadata/tyencode.rs index 73996518a1564..8cd18d1bfc7e8 100644 --- a/src/librustc_metadata/tyencode.rs +++ b/src/librustc_metadata/tyencode.rs @@ -28,7 +28,7 @@ use rustc::hir; use syntax::abi::Abi; use syntax::ast; -use rbml::leb128; +use rustc_serialize::leb128; use encoder; pub struct ctxt<'a, 'tcx: 'a> { @@ -186,9 +186,10 @@ pub fn enc_ty<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, t: Ty<'tcx abbrev.write_all(b"#"); { let start_position = abbrev.position() as usize; + let meta_start = 8 + ::common::metadata_encoding_version.len() as u64; let bytes_written = leb128::write_unsigned_leb128(abbrev.get_mut(), start_position, - pos); + pos - meta_start); abbrev.set_position((start_position + bytes_written) as u64); } diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index a6581ae605b56..a10f8c77ac05f 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -1346,8 +1346,7 @@ fn write_metadata(cx: &SharedCrateContext, cx.export_map(), cx.link_meta(), reachable_ids, - cx.mir_map(), - cx.tcx().map.krate()); + cx.mir_map()); let mut compressed = cstore.metadata_encoding_version().to_vec(); compressed.extend_from_slice(&flate::deflate_bytes(&metadata)); diff --git a/src/librbml/leb128.rs b/src/libserialize/leb128.rs similarity index 100% rename from src/librbml/leb128.rs rename to src/libserialize/leb128.rs diff --git a/src/libserialize/lib.rs b/src/libserialize/lib.rs index 7082ee5d292df..7cb02e2412c65 100644 --- a/src/libserialize/lib.rs +++ b/src/libserialize/lib.rs @@ -56,6 +56,9 @@ mod collection_impls; pub mod hex; pub mod json; +pub mod opaque; +pub mod leb128; + mod rustc_serialize { pub use serialize::*; } diff --git a/src/librbml/opaque.rs b/src/libserialize/opaque.rs similarity index 64% rename from src/librbml/opaque.rs rename to src/libserialize/opaque.rs index 55ab2afe4454d..e97834f63cee4 100644 --- a/src/librbml/opaque.rs +++ b/src/libserialize/opaque.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use Error as DecodeError; use leb128::{read_signed_leb128, read_unsigned_leb128, write_signed_leb128, write_unsigned_leb128}; use std::io::{self, Write}; use serialize; @@ -125,131 +124,6 @@ impl<'a> serialize::Encoder for Encoder<'a> { let _ = self.cursor.write_all(v.as_bytes()); Ok(()) } - - fn emit_enum(&mut self, _name: &str, f: F) -> EncodeResult - where F: FnOnce(&mut Self) -> EncodeResult - { - f(self) - } - - fn emit_enum_variant(&mut self, - _v_name: &str, - v_id: usize, - _len: usize, - f: F) - -> EncodeResult - where F: FnOnce(&mut Self) -> EncodeResult - { - self.emit_usize(v_id)?; - f(self) - } - - fn emit_enum_variant_arg(&mut self, _: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Encoder<'a>) -> EncodeResult - { - f(self) - } - - fn emit_enum_struct_variant(&mut self, - v_name: &str, - v_id: usize, - cnt: usize, - f: F) - -> EncodeResult - where F: FnOnce(&mut Encoder<'a>) -> EncodeResult - { - self.emit_enum_variant(v_name, v_id, cnt, f) - } - - fn emit_enum_struct_variant_field(&mut self, _: &str, idx: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Encoder<'a>) -> EncodeResult - { - self.emit_enum_variant_arg(idx, f) - } - - fn emit_struct(&mut self, _: &str, _len: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Encoder<'a>) -> EncodeResult - { - f(self) - } - - fn emit_struct_field(&mut self, _name: &str, _: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Encoder<'a>) -> EncodeResult - { - f(self) - } - - fn emit_tuple(&mut self, len: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Encoder<'a>) -> EncodeResult - { - self.emit_seq(len, f) - } - - fn emit_tuple_arg(&mut self, idx: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Encoder<'a>) -> EncodeResult - { - self.emit_seq_elt(idx, f) - } - - fn emit_tuple_struct(&mut self, _: &str, len: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Encoder<'a>) -> EncodeResult - { - self.emit_seq(len, f) - } - - fn emit_tuple_struct_arg(&mut self, idx: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Encoder<'a>) -> EncodeResult - { - self.emit_seq_elt(idx, f) - } - - fn emit_option(&mut self, f: F) -> EncodeResult - where F: FnOnce(&mut Encoder<'a>) -> EncodeResult - { - self.emit_enum("Option", f) - } - - fn emit_option_none(&mut self) -> EncodeResult { - self.emit_enum_variant("None", 0, 0, |_| Ok(())) - } - - fn emit_option_some(&mut self, f: F) -> EncodeResult - where F: FnOnce(&mut Encoder<'a>) -> EncodeResult - { - self.emit_enum_variant("Some", 1, 1, f) - } - - fn emit_seq(&mut self, len: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Encoder<'a>) -> EncodeResult - { - self.emit_usize(len)?; - f(self) - } - - fn emit_seq_elt(&mut self, _idx: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Encoder<'a>) -> EncodeResult - { - f(self) - } - - fn emit_map(&mut self, len: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Encoder<'a>) -> EncodeResult - { - self.emit_usize(len)?; - f(self) - } - - fn emit_map_elt_key(&mut self, _idx: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Encoder<'a>) -> EncodeResult - { - f(self) - } - - fn emit_map_elt_val(&mut self, _idx: usize, f: F) -> EncodeResult - where F: FnOnce(&mut Encoder<'a>) -> EncodeResult - { - f(self) - } } impl<'a> Encoder<'a> { @@ -302,7 +176,7 @@ macro_rules! read_sleb128 { impl<'a> serialize::Decoder for Decoder<'a> { - type Error = DecodeError; + type Error = String; fn read_nil(&mut self) -> Result<(), Self::Error> { Ok(()) @@ -379,138 +253,8 @@ impl<'a> serialize::Decoder for Decoder<'a> { Ok(s.to_string()) } - fn read_enum(&mut self, _name: &str, f: F) -> Result - where F: FnOnce(&mut Decoder<'a>) -> Result - { - f(self) - } - - fn read_enum_variant(&mut self, _: &[&str], mut f: F) -> Result - where F: FnMut(&mut Decoder<'a>, usize) -> Result - { - let disr = self.read_usize()?; - f(self, disr) - } - - fn read_enum_variant_arg(&mut self, _idx: usize, f: F) -> Result - where F: FnOnce(&mut Decoder<'a>) -> Result - { - f(self) - } - - fn read_enum_struct_variant(&mut self, _: &[&str], mut f: F) -> Result - where F: FnMut(&mut Decoder<'a>, usize) -> Result - { - let disr = self.read_usize()?; - f(self, disr) - } - - fn read_enum_struct_variant_field(&mut self, - _name: &str, - _idx: usize, - f: F) - -> Result - where F: FnOnce(&mut Decoder<'a>) -> Result - { - f(self) - } - - fn read_struct(&mut self, _name: &str, _: usize, f: F) -> Result - where F: FnOnce(&mut Decoder<'a>) -> Result - { - f(self) - } - - fn read_struct_field(&mut self, _name: &str, _idx: usize, f: F) -> Result - where F: FnOnce(&mut Decoder<'a>) -> Result - { - f(self) - } - - fn read_tuple(&mut self, tuple_len: usize, f: F) -> Result - where F: FnOnce(&mut Decoder<'a>) -> Result - { - self.read_seq(move |d, len| { - if len == tuple_len { - f(d) - } else { - let err = format!("Invalid tuple length. Expected {}, found {}", - tuple_len, - len); - Err(DecodeError::Expected(err)) - } - }) - } - - fn read_tuple_arg(&mut self, idx: usize, f: F) -> Result - where F: FnOnce(&mut Decoder<'a>) -> Result - { - self.read_seq_elt(idx, f) - } - - fn read_tuple_struct(&mut self, _name: &str, len: usize, f: F) -> Result - where F: FnOnce(&mut Decoder<'a>) -> Result - { - self.read_tuple(len, f) - } - - fn read_tuple_struct_arg(&mut self, idx: usize, f: F) -> Result - where F: FnOnce(&mut Decoder<'a>) -> Result - { - self.read_tuple_arg(idx, f) - } - - fn read_option(&mut self, mut f: F) -> Result - where F: FnMut(&mut Decoder<'a>, bool) -> Result - { - self.read_enum("Option", move |this| { - this.read_enum_variant(&["None", "Some"], move |this, idx| { - match idx { - 0 => f(this, false), - 1 => f(this, true), - _ => { - let msg = format!("Invalid Option index: {}", idx); - Err(DecodeError::Expected(msg)) - } - } - }) - }) - } - - fn read_seq(&mut self, f: F) -> Result - where F: FnOnce(&mut Decoder<'a>, usize) -> Result - { - let len = self.read_usize()?; - f(self, len) - } - - fn read_seq_elt(&mut self, _idx: usize, f: F) -> Result - where F: FnOnce(&mut Decoder<'a>) -> Result - { - f(self) - } - - fn read_map(&mut self, f: F) -> Result - where F: FnOnce(&mut Decoder<'a>, usize) -> Result - { - let len = self.read_usize()?; - f(self, len) - } - - fn read_map_elt_key(&mut self, _idx: usize, f: F) -> Result - where F: FnOnce(&mut Decoder<'a>) -> Result - { - f(self) - } - - fn read_map_elt_val(&mut self, _idx: usize, f: F) -> Result - where F: FnOnce(&mut Decoder<'a>) -> Result - { - f(self) - } - fn error(&mut self, err: &str) -> Self::Error { - DecodeError::ApplicationError(err.to_string()) + err.to_string() } } diff --git a/src/libserialize/serialize.rs b/src/libserialize/serialize.rs index ba6eefe82bbc6..88f6c12e98040 100644 --- a/src/libserialize/serialize.rs +++ b/src/libserialize/serialize.rs @@ -42,66 +42,99 @@ pub trait Encoder { fn emit_str(&mut self, v: &str) -> Result<(), Self::Error>; // Compound types: - fn emit_enum(&mut self, name: &str, f: F) -> Result<(), Self::Error> - where F: FnOnce(&mut Self) -> Result<(), Self::Error>; + fn emit_enum(&mut self, _name: &str, f: F) -> Result<(), Self::Error> + where F: FnOnce(&mut Self) -> Result<(), Self::Error> { f(self) } - fn emit_enum_variant(&mut self, v_name: &str, + fn emit_enum_variant(&mut self, _v_name: &str, v_id: usize, - len: usize, + _len: usize, f: F) -> Result<(), Self::Error> - where F: FnOnce(&mut Self) -> Result<(), Self::Error>; - fn emit_enum_variant_arg(&mut self, a_idx: usize, f: F) + where F: FnOnce(&mut Self) -> Result<(), Self::Error> + { + self.emit_usize(v_id)?; + f(self) + } + fn emit_enum_variant_arg(&mut self, _a_idx: usize, f: F) -> Result<(), Self::Error> - where F: FnOnce(&mut Self) -> Result<(), Self::Error>; + where F: FnOnce(&mut Self) -> Result<(), Self::Error> { f(self) } fn emit_enum_struct_variant(&mut self, v_name: &str, v_id: usize, len: usize, f: F) -> Result<(), Self::Error> - where F: FnOnce(&mut Self) -> Result<(), Self::Error>; + where F: FnOnce(&mut Self) -> Result<(), Self::Error> + { + self.emit_enum_variant(v_name, v_id, len, f) + } fn emit_enum_struct_variant_field(&mut self, - f_name: &str, + _f_name: &str, f_idx: usize, f: F) -> Result<(), Self::Error> - where F: FnOnce(&mut Self) -> Result<(), Self::Error>; + where F: FnOnce(&mut Self) -> Result<(), Self::Error> + { + self.emit_enum_variant_arg(f_idx, f) + } - fn emit_struct(&mut self, name: &str, len: usize, f: F) + fn emit_struct(&mut self, _name: &str, _len: usize, f: F) -> Result<(), Self::Error> - where F: FnOnce(&mut Self) -> Result<(), Self::Error>; - fn emit_struct_field(&mut self, f_name: &str, f_idx: usize, f: F) + where F: FnOnce(&mut Self) -> Result<(), Self::Error> { f(self) } + fn emit_struct_field(&mut self, _f_name: &str, _f_idx: usize, f: F) -> Result<(), Self::Error> - where F: FnOnce(&mut Self) -> Result<(), Self::Error>; + where F: FnOnce(&mut Self) -> Result<(), Self::Error> { f(self) } - fn emit_tuple(&mut self, len: usize, f: F) -> Result<(), Self::Error> - where F: FnOnce(&mut Self) -> Result<(), Self::Error>; - fn emit_tuple_arg(&mut self, idx: usize, f: F) -> Result<(), Self::Error> - where F: FnOnce(&mut Self) -> Result<(), Self::Error>; + fn emit_tuple(&mut self, _len: usize, f: F) -> Result<(), Self::Error> + where F: FnOnce(&mut Self) -> Result<(), Self::Error> { f(self) } + fn emit_tuple_arg(&mut self, _idx: usize, f: F) -> Result<(), Self::Error> + where F: FnOnce(&mut Self) -> Result<(), Self::Error> { f(self) } - fn emit_tuple_struct(&mut self, name: &str, len: usize, f: F) + fn emit_tuple_struct(&mut self, _name: &str, len: usize, f: F) -> Result<(), Self::Error> - where F: FnOnce(&mut Self) -> Result<(), Self::Error>; + where F: FnOnce(&mut Self) -> Result<(), Self::Error> + { + self.emit_tuple(len, f) + } fn emit_tuple_struct_arg(&mut self, f_idx: usize, f: F) -> Result<(), Self::Error> - where F: FnOnce(&mut Self) -> Result<(), Self::Error>; + where F: FnOnce(&mut Self) -> Result<(), Self::Error> + { + self.emit_tuple_arg(f_idx, f) + } // Specialized types: fn emit_option(&mut self, f: F) -> Result<(), Self::Error> - where F: FnOnce(&mut Self) -> Result<(), Self::Error>; - fn emit_option_none(&mut self) -> Result<(), Self::Error>; + where F: FnOnce(&mut Self) -> Result<(), Self::Error> + { + self.emit_enum("Option", f) + } + fn emit_option_none(&mut self) -> Result<(), Self::Error> { + self.emit_enum_variant("None", 0, 0, |_| Ok(())) + } fn emit_option_some(&mut self, f: F) -> Result<(), Self::Error> - where F: FnOnce(&mut Self) -> Result<(), Self::Error>; + where F: FnOnce(&mut Self) -> Result<(), Self::Error> + { + + self.emit_enum_variant("Some", 1, 1, f) + } fn emit_seq(&mut self, len: usize, f: F) -> Result<(), Self::Error> - where F: FnOnce(&mut Self) -> Result<(), Self::Error>; - fn emit_seq_elt(&mut self, idx: usize, f: F) -> Result<(), Self::Error> - where F: FnOnce(&mut Self) -> Result<(), Self::Error>; + where F: FnOnce(&mut Self) -> Result<(), Self::Error> + { + self.emit_usize(len)?; + f(self) + } + fn emit_seq_elt(&mut self, _idx: usize, f: F) -> Result<(), Self::Error> + where F: FnOnce(&mut Self) -> Result<(), Self::Error> { f(self) } fn emit_map(&mut self, len: usize, f: F) -> Result<(), Self::Error> - where F: FnOnce(&mut Self) -> Result<(), Self::Error>; - fn emit_map_elt_key(&mut self, idx: usize, f: F) -> Result<(), Self::Error> - where F: FnOnce(&mut Self) -> Result<(), Self::Error>; - fn emit_map_elt_val(&mut self, idx: usize, f: F) -> Result<(), Self::Error> - where F: FnOnce(&mut Self) -> Result<(), Self::Error>; + where F: FnOnce(&mut Self) -> Result<(), Self::Error> + { + self.emit_usize(len)?; + f(self) + } + fn emit_map_elt_key(&mut self, _idx: usize, f: F) -> Result<(), Self::Error> + where F: FnOnce(&mut Self) -> Result<(), Self::Error> { f(self) } + fn emit_map_elt_val(&mut self, _idx: usize, f: F) -> Result<(), Self::Error> + where F: FnOnce(&mut Self) -> Result<(), Self::Error> { f(self) } } pub trait Decoder { @@ -126,66 +159,101 @@ pub trait Decoder { fn read_str(&mut self) -> Result; // Compound types: - fn read_enum(&mut self, name: &str, f: F) -> Result - where F: FnOnce(&mut Self) -> Result; + fn read_enum(&mut self, _name: &str, f: F) -> Result + where F: FnOnce(&mut Self) -> Result { f(self) } - fn read_enum_variant(&mut self, names: &[&str], f: F) + fn read_enum_variant(&mut self, _names: &[&str], mut f: F) -> Result - where F: FnMut(&mut Self, usize) -> Result; - fn read_enum_variant_arg(&mut self, a_idx: usize, f: F) + where F: FnMut(&mut Self, usize) -> Result + { + let disr = self.read_usize()?; + f(self, disr) + } + fn read_enum_variant_arg(&mut self, _a_idx: usize, f: F) -> Result - where F: FnOnce(&mut Self) -> Result; + where F: FnOnce(&mut Self) -> Result { f(self) } fn read_enum_struct_variant(&mut self, names: &[&str], f: F) -> Result - where F: FnMut(&mut Self, usize) -> Result; + where F: FnMut(&mut Self, usize) -> Result + { + self.read_enum_variant(names, f) + } fn read_enum_struct_variant_field(&mut self, - &f_name: &str, + _f_name: &str, f_idx: usize, f: F) -> Result - where F: FnOnce(&mut Self) -> Result; + where F: FnOnce(&mut Self) -> Result + { + self.read_enum_variant_arg(f_idx, f) + } - fn read_struct(&mut self, s_name: &str, len: usize, f: F) + fn read_struct(&mut self, _s_name: &str, _len: usize, f: F) -> Result - where F: FnOnce(&mut Self) -> Result; + where F: FnOnce(&mut Self) -> Result { f(self) } fn read_struct_field(&mut self, - f_name: &str, - f_idx: usize, + _f_name: &str, + _f_idx: usize, f: F) -> Result - where F: FnOnce(&mut Self) -> Result; + where F: FnOnce(&mut Self) -> Result { f(self) } - fn read_tuple(&mut self, len: usize, f: F) -> Result - where F: FnOnce(&mut Self) -> Result; - fn read_tuple_arg(&mut self, a_idx: usize, f: F) + fn read_tuple(&mut self, _len: usize, f: F) -> Result + where F: FnOnce(&mut Self) -> Result { f(self) } + fn read_tuple_arg(&mut self, _a_idx: usize, f: F) -> Result - where F: FnOnce(&mut Self) -> Result; + where F: FnOnce(&mut Self) -> Result { f(self) } - fn read_tuple_struct(&mut self, s_name: &str, len: usize, f: F) + fn read_tuple_struct(&mut self, _s_name: &str, len: usize, f: F) -> Result - where F: FnOnce(&mut Self) -> Result; + where F: FnOnce(&mut Self) -> Result + { + self.read_tuple(len, f) + } fn read_tuple_struct_arg(&mut self, a_idx: usize, f: F) -> Result - where F: FnOnce(&mut Self) -> Result; + where F: FnOnce(&mut Self) -> Result + { + self.read_tuple_arg(a_idx, f) + } // Specialized types: - fn read_option(&mut self, f: F) -> Result - where F: FnMut(&mut Self, bool) -> Result; + fn read_option(&mut self, mut f: F) -> Result + where F: FnMut(&mut Self, bool) -> Result + { + self.read_enum("Option", move |this| { + this.read_enum_variant(&["None", "Some"], move |this, idx| { + match idx { + 0 => f(this, false), + 1 => f(this, true), + _ => Err(this.error("read_option: expected 0 for None or 1 for Some")), + } + }) + }) + } fn read_seq(&mut self, f: F) -> Result - where F: FnOnce(&mut Self, usize) -> Result; - fn read_seq_elt(&mut self, idx: usize, f: F) -> Result - where F: FnOnce(&mut Self) -> Result; + where F: FnOnce(&mut Self, usize) -> Result + { + let len = self.read_usize()?; + f(self, len) + } + fn read_seq_elt(&mut self, _idx: usize, f: F) -> Result + where F: FnOnce(&mut Self) -> Result { f(self) } fn read_map(&mut self, f: F) -> Result - where F: FnOnce(&mut Self, usize) -> Result; - fn read_map_elt_key(&mut self, idx: usize, f: F) + where F: FnOnce(&mut Self, usize) -> Result + { + let len = self.read_usize()?; + f(self, len) + } + fn read_map_elt_key(&mut self, _idx: usize, f: F) -> Result - where F: FnOnce(&mut Self) -> Result; - fn read_map_elt_val(&mut self, idx: usize, f: F) + where F: FnOnce(&mut Self) -> Result { f(self) } + fn read_map_elt_val(&mut self, _idx: usize, f: F) -> Result - where F: FnOnce(&mut Self) -> Result; + where F: FnOnce(&mut Self) -> Result { f(self) } // Failure fn error(&mut self, err: &str) -> Self::Error; diff --git a/src/rustc/Cargo.lock b/src/rustc/Cargo.lock index 3377fc43d8a60..d8a02badceede 100644 --- a/src/rustc/Cargo.lock +++ b/src/rustc/Cargo.lock @@ -50,14 +50,6 @@ dependencies = [ "syntax_pos 0.0.0", ] -[[package]] -name = "rbml" -version = "0.0.0" -dependencies = [ - "log 0.0.0", - "serialize 0.0.0", -] - [[package]] name = "rustc" version = "0.0.0" @@ -67,7 +59,6 @@ dependencies = [ "fmt_macros 0.0.0", "graphviz 0.0.0", "log 0.0.0", - "rbml 0.0.0", "rustc_back 0.0.0", "rustc_bitflags 0.0.0", "rustc_const_math 0.0.0", @@ -185,7 +176,6 @@ version = "0.0.0" dependencies = [ "graphviz 0.0.0", "log 0.0.0", - "rbml 0.0.0", "rustc 0.0.0", "rustc_data_structures 0.0.0", "serialize 0.0.0", @@ -227,7 +217,6 @@ version = "0.0.0" dependencies = [ "flate 0.0.0", "log 0.0.0", - "rbml 0.0.0", "rustc 0.0.0", "rustc_back 0.0.0", "rustc_bitflags 0.0.0", diff --git a/src/test/run-pass-fulldeps/issue-11881.rs b/src/test/run-pass-fulldeps/issue-11881.rs index 9da04f7235531..8369d08db36d4 100644 --- a/src/test/run-pass-fulldeps/issue-11881.rs +++ b/src/test/run-pass-fulldeps/issue-11881.rs @@ -11,7 +11,6 @@ #![feature(rustc_private)] -extern crate rbml; extern crate serialize; use std::io::Cursor; @@ -21,8 +20,7 @@ use std::slice; use serialize::{Encodable, Encoder}; use serialize::json; - -use rbml::writer; +use serialize::opaque; #[derive(Encodable)] struct Foo { @@ -44,7 +42,7 @@ fn encode_json(val: &T, wr: &mut Cursor>) { write!(wr, "{}", json::as_json(val)); } fn encode_rbml(val: &T, wr: &mut Cursor>) { - let mut encoder = writer::Encoder::new(wr); + let mut encoder = opaque::Encoder::new(wr); val.encode(&mut encoder); } From bcbb4107a1a966ea8ad48d370f553dffde780392 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Fri, 2 Sep 2016 00:49:29 +0300 Subject: [PATCH 17/39] rustc_metadata: side-step ty{en,de}code for everything but Ty. --- src/librustc/ty/mod.rs | 18 ++-- src/librustc/ty/sty.rs | 10 +- src/librustc/ty/subst.rs | 37 ++++++- src/librustc_metadata/decoder.rs | 65 ++++++------ src/librustc_metadata/encoder.rs | 39 +------ src/librustc_metadata/tydecode.rs | 164 ++---------------------------- src/librustc_metadata/tyencode.rs | 146 ++------------------------ 7 files changed, 99 insertions(+), 380 deletions(-) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 6cabc25df6afa..d4dd8298db3e2 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -668,7 +668,7 @@ pub enum IntVarValue { /// from `T:'a` annotations appearing in the type definition. If /// this is `None`, then the default is inherited from the /// surrounding context. See RFC #599 for details. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, RustcEncodable, RustcDecodable)] pub enum ObjectLifetimeDefault<'tcx> { /// Require an explicit annotation. Occurs when multiple /// `T:'a` constraints are found. @@ -681,7 +681,7 @@ pub enum ObjectLifetimeDefault<'tcx> { Specific(&'tcx Region), } -#[derive(Clone)] +#[derive(Clone, RustcEncodable, RustcDecodable)] pub struct TypeParameterDef<'tcx> { pub name: Name, pub def_id: DefId, @@ -691,7 +691,7 @@ pub struct TypeParameterDef<'tcx> { pub object_lifetime_default: ObjectLifetimeDefault<'tcx>, } -#[derive(Clone)] +#[derive(Clone, RustcEncodable, RustcDecodable)] pub struct RegionParameterDef<'tcx> { pub name: Name, pub def_id: DefId, @@ -719,7 +719,7 @@ impl<'tcx> RegionParameterDef<'tcx> { /// Information about the formal type/lifetime parameters associated /// with an item or method. Analogous to hir::Generics. -#[derive(Clone, Debug)] +#[derive(Clone, Debug, RustcEncodable, RustcDecodable)] pub struct Generics<'tcx> { pub parent: Option, pub parent_regions: u32, @@ -786,7 +786,7 @@ impl<'a, 'gcx, 'tcx> GenericPredicates<'tcx> { } } -#[derive(Clone, PartialEq, Eq, Hash)] +#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub enum Predicate<'tcx> { /// Corresponds to `where Foo : Bar`. `Foo` here would be /// the `Self` type of the trait reference and `A`, `B`, and `C` @@ -910,7 +910,7 @@ impl<'a, 'gcx, 'tcx> Predicate<'tcx> { } } -#[derive(Clone, PartialEq, Eq, Hash)] +#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub struct TraitPredicate<'tcx> { pub trait_ref: TraitRef<'tcx> } @@ -967,11 +967,11 @@ impl<'tcx> PolyTraitPredicate<'tcx> { } } -#[derive(Clone, PartialEq, Eq, Hash, Debug)] +#[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] pub struct EquatePredicate<'tcx>(pub Ty<'tcx>, pub Ty<'tcx>); // `0 == 1` pub type PolyEquatePredicate<'tcx> = ty::Binder>; -#[derive(Clone, PartialEq, Eq, Hash, Debug)] +#[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] pub struct OutlivesPredicate(pub A, pub B); // `A : B` pub type PolyOutlivesPredicate = ty::Binder>; pub type PolyRegionOutlivesPredicate<'tcx> = PolyOutlivesPredicate<&'tcx ty::Region, @@ -990,7 +990,7 @@ pub type PolyTypeOutlivesPredicate<'tcx> = PolyOutlivesPredicate, &'tcx /// equality between arbitrary types. Processing an instance of Form /// #2 eventually yields one of these `ProjectionPredicate` /// instances to normalize the LHS. -#[derive(Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub struct ProjectionPredicate<'tcx> { pub projection_ty: ProjectionTy<'tcx>, pub ty: Ty<'tcx>, diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 5176fb665fbfb..0f2ff8a689fa3 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -290,7 +290,7 @@ pub struct TraitObject<'tcx> { /// Note that a `TraitRef` introduces a level of region binding, to /// account for higher-ranked trait bounds like `T : for<'a> Foo<&'a /// U>` or higher-ranked object types. -#[derive(Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub struct TraitRef<'tcx> { pub def_id: DefId, pub substs: &'tcx Substs<'tcx>, @@ -366,7 +366,7 @@ impl<'tcx> PolyExistentialTraitRef<'tcx> { /// erase, or otherwise "discharge" these bound regions, we change the /// type from `Binder` to just `T` (see /// e.g. `liberate_late_bound_regions`). -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] pub struct Binder(pub T); impl Binder { @@ -414,7 +414,7 @@ impl fmt::Debug for TypeFlags { /// Represents the projection of an associated type. In explicit UFCS /// form this would be written `>::N`. -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] pub struct ProjectionTy<'tcx> { /// The trait reference `T as Trait<..>`. pub trait_ref: ty::TraitRef<'tcx>, @@ -430,7 +430,7 @@ pub struct BareFnTy<'tcx> { pub sig: PolyFnSig<'tcx>, } -#[derive(Clone, PartialEq, Eq, Hash)] +#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub struct ClosureTy<'tcx> { pub unsafety: hir::Unsafety, pub abi: abi::Abi, @@ -443,7 +443,7 @@ pub struct ClosureTy<'tcx> { /// - `inputs` is the list of arguments and their modes. /// - `output` is the return type. /// - `variadic` indicates whether this is a variadic function. (only true for foreign fns) -#[derive(Clone, PartialEq, Eq, Hash)] +#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub struct FnSig<'tcx> { pub inputs: Vec>, pub output: Ty<'tcx>, diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index 6b493118bcfd0..6911d2174260d 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -14,7 +14,7 @@ use hir::def_id::DefId; use ty::{self, Ty, TyCtxt}; use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; -use serialize; +use serialize::{self, Encodable, Encoder, Decodable, Decoder}; use syntax_pos::{Span, DUMMY_SP}; use core::nonzero::NonZero; @@ -128,8 +128,40 @@ impl<'tcx> TypeFoldable<'tcx> for Kind<'tcx> { } } +impl<'tcx> Encodable for Kind<'tcx> { + fn encode(&self, e: &mut E) -> Result<(), E::Error> { + e.emit_enum("Kind", |e| { + if let Some(ty) = self.as_type() { + e.emit_enum_variant("Ty", TYPE_TAG, 1, |e| { + e.emit_enum_variant_arg(0, |e| ty.encode(e)) + }) + } else if let Some(r) = self.as_region() { + e.emit_enum_variant("Region", REGION_TAG, 1, |e| { + e.emit_enum_variant_arg(0, |e| r.encode(e)) + }) + } else { + bug!() + } + }) + } +} + +impl<'tcx> Decodable for Kind<'tcx> { + fn decode(d: &mut D) -> Result, D::Error> { + d.read_enum("Kind", |d| { + d.read_enum_variant(&["Ty", "Region"], |d, tag| { + match tag { + TYPE_TAG => Ty::decode(d).map(Kind::from), + REGION_TAG => <&ty::Region>::decode(d).map(Kind::from), + _ => Err(d.error("invalid Kind tag")) + } + }) + }) + } +} + /// A substitution mapping type/region parameters to new values. -#[derive(Clone, PartialEq, Eq, Debug, Hash)] +#[derive(Clone, PartialEq, Eq, Debug, Hash, RustcEncodable, RustcDecodable)] pub struct Substs<'tcx> { params: Vec> } @@ -297,7 +329,6 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx Substs<'tcx> { } } -impl<'tcx> serialize::UseSpecializedEncodable for &'tcx Substs<'tcx> {} impl<'tcx> serialize::UseSpecializedDecodable for &'tcx Substs<'tcx> {} /////////////////////////////////////////////////////////////////////////// diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index ba593e5be9980..d3c04874a08ef 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -94,16 +94,6 @@ impl<'a, 'tcx> DecodeContext<'a, 'tcx> { pub fn cdata(&self) -> &'a cstore::CrateMetadata { self.cdata.expect("missing CrateMetadata in DecodeContext") } - - fn read_ty_encoded(&mut self, op: F) -> R - where F: for<'x> FnOnce(&mut TyDecoder<'x,'tcx>) -> R - { - let pos = self.opaque.position(); - let doc = rbml::Doc::at(self.opaque.data, pos); - self.opaque.advance(doc.end - pos); - op(&mut TyDecoder::with_doc(self.tcx(), self.cdata().cnum, doc, - &mut |d| translate_def_id(self.cdata(), d))) - } } macro_rules! decoder_methods { @@ -243,13 +233,19 @@ impl<'a, 'tcx> SpecializedDecoder for DecodeContext<'a, 'tcx> { impl<'a, 'tcx> SpecializedDecoder> for DecodeContext<'a, 'tcx> { fn specialized_decode(&mut self) -> Result, Self::Error> { - Ok(self.read_ty_encoded(|d| d.parse_ty())) + let pos = self.opaque.position(); + let doc = rbml::Doc::at(self.opaque.data, pos); + self.opaque.advance(doc.end - pos); + Ok(TyDecoder::with_doc(self.tcx(), self.cdata().cnum, doc, + &mut |d| translate_def_id(self.cdata(), d)) + .parse_ty()) } } impl<'a, 'tcx> SpecializedDecoder<&'tcx Substs<'tcx>> for DecodeContext<'a, 'tcx> { fn specialized_decode(&mut self) -> Result<&'tcx Substs<'tcx>, Self::Error> { - Ok(self.read_ty_encoded(|d| d.parse_substs())) + let substs = Substs::decode(self)?; + Ok(self.tcx().mk_substs(substs)) } } @@ -469,26 +465,25 @@ fn variant_disr_val(d: rbml::Doc) -> u64 { } fn doc_type<'a, 'tcx>(doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>, cdata: Cmd) -> Ty<'tcx> { - let tp = reader::get_doc(doc, tag_items_data_item_type); - TyDecoder::with_doc(tcx, cdata.cnum, tp, - &mut |did| translate_def_id(cdata, did)) - .parse_ty() + maybe_doc_type(doc, tcx, cdata).expect("missing tag_items_data_item_type") } fn maybe_doc_type<'a, 'tcx>(doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>, cdata: Cmd) -> Option> { reader::maybe_get_doc(doc, tag_items_data_item_type).map(|tp| { - TyDecoder::with_doc(tcx, cdata.cnum, tp, - &mut |did| translate_def_id(cdata, did)) - .parse_ty() + let mut dcx = tp.decoder(); + dcx.tcx = Some(tcx); + dcx.cdata = Some(cdata); + Decodable::decode(&mut dcx).unwrap() }) } fn doc_trait_ref<'a, 'tcx>(doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>, cdata: Cmd) -> ty::TraitRef<'tcx> { - TyDecoder::with_doc(tcx, cdata.cnum, doc, - &mut |did| translate_def_id(cdata, did)) - .parse_trait_ref() + let mut dcx = doc.decoder(); + dcx.tcx = Some(tcx); + dcx.cdata = Some(cdata); + Decodable::decode(&mut dcx).unwrap() } fn item_trait_ref<'a, 'tcx>(doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>, cdata: Cmd) @@ -1628,10 +1623,10 @@ fn doc_generics<'a, 'tcx>(base_doc: rbml::Doc, cdata: Cmd) -> &'tcx ty::Generics<'tcx> { - let doc = reader::get_doc(base_doc, tag_item_generics); - TyDecoder::with_doc(tcx, cdata.cnum, doc, - &mut |did| translate_def_id(cdata, did)) - .parse_generics() + let mut dcx = reader::get_doc(base_doc, tag_item_generics).decoder(); + dcx.tcx = Some(tcx); + dcx.cdata = Some(cdata); + tcx.alloc_generics(Decodable::decode(&mut dcx).unwrap()) } fn doc_predicate<'a, 'tcx>(cdata: Cmd, @@ -1641,10 +1636,14 @@ fn doc_predicate<'a, 'tcx>(cdata: Cmd, { let predicate_pos = cdata.xref_index.lookup( cdata.data(), reader::doc_as_u32(doc)).unwrap() as usize; - TyDecoder::new( - cdata.data(), cdata.cnum, predicate_pos, tcx, - &mut |did| translate_def_id(cdata, did) - ).parse_predicate() + let mut dcx = rbml::Doc { + data: cdata.data(), + start: predicate_pos, + end: cdata.data().len(), + }.decoder(); + dcx.tcx = Some(tcx); + dcx.cdata = Some(cdata); + Decodable::decode(&mut dcx).unwrap() } fn doc_predicates<'a, 'tcx>(base_doc: rbml::Doc, @@ -1694,8 +1693,10 @@ pub fn closure_ty<'a, 'tcx>(cdata: Cmd, closure_id: DefIndex, tcx: TyCtxt<'a, 't -> ty::ClosureTy<'tcx> { let closure_doc = cdata.lookup_item(closure_id); let closure_ty_doc = reader::get_doc(closure_doc, tag_items_closure_ty); - TyDecoder::with_doc(tcx, cdata.cnum, closure_ty_doc, &mut |did| translate_def_id(cdata, did)) - .parse_closure_ty() + let mut dcx = closure_ty_doc.decoder(); + dcx.tcx = Some(tcx); + dcx.cdata = Some(cdata); + Decodable::decode(&mut dcx).unwrap() } pub fn def_key(cdata: Cmd, id: DefIndex) -> hir_map::DefKey { diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 4b603fcb1055d..dcc3d13631eba 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -28,7 +28,6 @@ use middle::dependency_format::Linkage; use rustc::dep_graph::DepNode; use rustc::traits::specialization_graph; use rustc::ty::{self, Ty, TyCtxt}; -use rustc::ty::subst::Substs; use rustc::hir::svh::Svh; use rustc::mir::mir_map::MirMap; @@ -126,17 +125,6 @@ impl<'a, 'tcx> SpecializedEncoder> for EncodeContext<'a, 'tcx> { } } -impl<'a, 'tcx> SpecializedEncoder<&'tcx Substs<'tcx>> for EncodeContext<'a, 'tcx> { - fn specialized_encode(&mut self, substs: &&'tcx Substs<'tcx>) -> Result<(), Self::Error> { - let cx = self.ty_str_ctxt(); - - self.start_tag(tag_opaque)?; - tyencode::enc_substs(&mut self.rbml_w.opaque.cursor, &cx, substs); - self.mark_stable_position(); - self.end_tag() - } -} - fn encode_name(ecx: &mut EncodeContext, name: Name) { ecx.wr_tagged_str(tag_paths_data_name, &name.as_str()); } @@ -163,10 +151,8 @@ fn encode_def_id_and_key(ecx: &mut EncodeContext, def_id: DefId) { fn encode_trait_ref<'a, 'tcx>(ecx: &mut EncodeContext<'a, 'tcx>, trait_ref: ty::TraitRef<'tcx>, tag: usize) { - let cx = ecx.ty_str_ctxt(); ecx.start_tag(tag); - tyencode::enc_trait_ref(&mut ecx.opaque.cursor, &cx, trait_ref); - ecx.mark_stable_position(); + trait_ref.encode(ecx).unwrap(); ecx.end_tag(); } @@ -211,19 +197,10 @@ fn encode_variant_id(ecx: &mut EncodeContext, vid: DefId) { ecx.wr_tagged_u64(tag_mod_child, id); } -fn write_closure_type<'a, 'tcx>(ecx: &mut EncodeContext<'a, 'tcx>, - closure_type: &ty::ClosureTy<'tcx>) { - let cx = ecx.ty_str_ctxt(); - tyencode::enc_closure_ty(&mut ecx.opaque.cursor, &cx, closure_type); - ecx.mark_stable_position(); -} - impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { fn encode_type(&mut self, typ: Ty<'tcx>) { - let cx = self.ty_str_ctxt(); self.start_tag(tag_items_data_item_type); - tyencode::enc_ty(&mut self.opaque.cursor, &cx, typ); - self.mark_stable_position(); + typ.encode(self.ecx).unwrap(); self.end_tag(); } @@ -519,10 +496,8 @@ impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { generics: &ty::Generics<'tcx>, predicates: &ty::GenericPredicates<'tcx>) { - let cx = self.ty_str_ctxt(); self.start_tag(tag_item_generics); - tyencode::enc_generics(&mut self.opaque.cursor, &cx, generics); - self.mark_stable_position(); + generics.encode(self.ecx).unwrap(); self.end_tag(); self.encode_predicates(predicates, tag_item_predicates); } @@ -859,7 +834,6 @@ fn encode_xrefs<'a, 'tcx>(ecx: &mut EncodeContext<'a, 'tcx>, xrefs: FnvHashMap, u32>) { let mut xref_positions = vec![0; xrefs.len()]; - let cx = ecx.ty_str_ctxt(); // Encode XRefs sorted by their ID let mut sorted_xrefs: Vec<_> = xrefs.into_iter().collect(); @@ -869,9 +843,7 @@ fn encode_xrefs<'a, 'tcx>(ecx: &mut EncodeContext<'a, 'tcx>, for (xref, id) in sorted_xrefs.into_iter() { xref_positions[id as usize] = ecx.mark_stable_position() as u32; match xref { - XRef::Predicate(p) => { - tyencode::enc_predicate(&mut ecx.opaque.cursor, &cx, &p) - } + XRef::Predicate(p) => p.encode(ecx).unwrap() } } ecx.mark_stable_position(); @@ -1396,8 +1368,7 @@ impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { encode_name(self, syntax::parse::token::intern("")); self.start_tag(tag_items_closure_ty); - write_closure_type(self, - &tcx.tables.borrow().closure_tys[&def_id]); + tcx.tables.borrow().closure_tys[&def_id].encode(self.ecx).unwrap(); self.end_tag(); self.start_tag(tag_items_closure_kind); diff --git a/src/librustc_metadata/tydecode.rs b/src/librustc_metadata/tydecode.rs index 28e7b8852b300..ccc4894fcdda2 100644 --- a/src/librustc_metadata/tydecode.rs +++ b/src/librustc_metadata/tydecode.rs @@ -21,7 +21,7 @@ use rustc::hir; use rustc::hir::def_id::{CrateNum, DefId, DefIndex}; use middle::region; use rustc::ty::subst::{Kind, Substs}; -use rustc::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable}; +use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; use rbml; use rustc_serialize::leb128; @@ -109,12 +109,6 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { value as usize } - fn parse_name(&mut self, last: char) -> ast::Name { - fn is_last(b: char, c: char) -> bool { return c == b; } - let bytes = self.scan(|a| is_last(last, a)); - token::intern(str::from_utf8(bytes).unwrap()) - } - fn parse_size(&mut self) -> Option { assert_eq!(self.next(), '/'); @@ -128,7 +122,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { } } - pub fn parse_substs(&mut self) -> &'tcx Substs<'tcx> { + fn parse_substs(&mut self) -> &'tcx Substs<'tcx> { let mut params = vec![]; assert_eq!(self.next(), '['); while self.peek() != ']' { @@ -144,34 +138,6 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { Substs::new(self.tcx, params) } - pub fn parse_generics(&mut self) -> &'tcx ty::Generics<'tcx> { - let parent = self.parse_opt(|this| this.parse_def()); - let parent_regions = self.parse_u32(); - assert_eq!(self.next(), '|'); - let parent_types = self.parse_u32(); - - let mut regions = vec![]; - let mut types = vec![]; - assert_eq!(self.next(), '['); - while self.peek() != '|' { - regions.push(self.parse_region_param_def()); - } - assert_eq!(self.next(), '|'); - while self.peek() != ']' { - types.push(self.parse_type_param_def()); - } - assert_eq!(self.next(), ']'); - - self.tcx.alloc_generics(ty::Generics { - parent: parent, - parent_regions: parent_regions, - parent_types: parent_types, - regions: regions, - types: types, - has_self: self.next() == 'S' - }) - } - fn parse_bound_region(&mut self) -> ty::BoundRegion { match self.next() { 'a' => { @@ -207,7 +173,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { } } - pub fn parse_region(&mut self) -> &'tcx ty::Region { + fn parse_region(&mut self) -> &'tcx ty::Region { self.tcx.mk_region(match self.next() { 'b' => { assert_eq!(self.next(), '['); @@ -300,16 +266,6 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { }) } - fn parse_opt(&mut self, f: F) -> Option - where F: FnOnce(&mut TyDecoder<'a, 'tcx>) -> T, - { - match self.next() { - 'n' => None, - 's' => Some(f(self)), - _ => bug!("parse_opt: bad input") - } - } - fn parse_str(&mut self, term: char) -> String { let mut result = String::new(); while self.peek() != term { @@ -321,14 +277,14 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { result } - pub fn parse_trait_ref(&mut self) -> ty::TraitRef<'tcx> { + fn parse_trait_ref(&mut self) -> ty::TraitRef<'tcx> { ty::TraitRef { def_id: self.parse_def(), substs: self.parse_substs() } } - pub fn parse_existential_trait_ref(&mut self) -> ty::ExistentialTraitRef<'tcx> { + fn parse_existential_trait_ref(&mut self) -> ty::ExistentialTraitRef<'tcx> { ty::ExistentialTraitRef { def_id: self.parse_def(), substs: self.parse_substs() @@ -538,18 +494,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { abi::lookup(&abi_str[..]).expect(abi_str) } - pub fn parse_closure_ty(&mut self) -> ty::ClosureTy<'tcx> { - let unsafety = parse_unsafety(self.next()); - let sig = self.parse_sig(); - let abi = self.parse_abi_set(); - ty::ClosureTy { - unsafety: unsafety, - sig: sig, - abi: abi, - } - } - - pub fn parse_bare_fn_ty(&mut self) -> &'tcx ty::BareFnTy<'tcx> { + fn parse_bare_fn_ty(&mut self) -> &'tcx ty::BareFnTy<'tcx> { let unsafety = parse_unsafety(self.next()); let abi = self.parse_abi_set(); let sig = self.parse_sig(); @@ -578,48 +523,6 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { variadic: variadic}) } - pub fn parse_predicate(&mut self) -> ty::Predicate<'tcx> { - match self.next() { - 't' => ty::Binder(self.parse_trait_ref()).to_predicate(), - 'e' => ty::Binder(ty::EquatePredicate(self.parse_ty(), - self.parse_ty())).to_predicate(), - 'r' => ty::Binder(ty::OutlivesPredicate(self.parse_region(), - self.parse_region())).to_predicate(), - 'o' => ty::Binder(ty::OutlivesPredicate(self.parse_ty(), - self.parse_region())).to_predicate(), - 'p' => ty::Binder(self.parse_projection_predicate()).to_predicate(), - 'w' => ty::Predicate::WellFormed(self.parse_ty()), - 'O' => { - let def_id = self.parse_def(); - assert_eq!(self.next(), '|'); - ty::Predicate::ObjectSafe(def_id) - } - 'c' => { - let def_id = self.parse_def(); - assert_eq!(self.next(), '|'); - let kind = match self.next() { - 'f' => ty::ClosureKind::Fn, - 'm' => ty::ClosureKind::FnMut, - 'o' => ty::ClosureKind::FnOnce, - c => bug!("Encountered invalid character in metadata: {}", c) - }; - assert_eq!(self.next(), '|'); - ty::Predicate::ClosureKind(def_id, kind) - } - c => bug!("Encountered invalid character in metadata: {}", c) - } - } - - fn parse_projection_predicate(&mut self) -> ty::ProjectionPredicate<'tcx> { - ty::ProjectionPredicate { - projection_ty: ty::ProjectionTy { - trait_ref: self.parse_trait_ref(), - item_name: token::intern(&self.parse_str('|')), - }, - ty: self.parse_ty(), - } - } - fn parse_existential_projection(&mut self) -> ty::ExistentialProjection<'tcx> { ty::ExistentialProjection { trait_ref: self.parse_existential_trait_ref(), @@ -628,61 +531,6 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { } } - fn parse_type_param_def(&mut self) -> ty::TypeParameterDef<'tcx> { - let name = self.parse_name(':'); - let def_id = self.parse_def(); - let index = self.parse_u32(); - assert_eq!(self.next(), '|'); - let default_def_id = self.parse_def(); - let default = self.parse_opt(|this| this.parse_ty()); - let object_lifetime_default = self.parse_object_lifetime_default(); - - ty::TypeParameterDef { - name: name, - def_id: def_id, - index: index, - default_def_id: default_def_id, - default: default, - object_lifetime_default: object_lifetime_default, - } - } - - fn parse_region_param_def(&mut self) -> ty::RegionParameterDef<'tcx> { - let name = self.parse_name(':'); - let def_id = self.parse_def(); - let index = self.parse_u32(); - assert_eq!(self.next(), '|'); - let mut bounds = vec![]; - loop { - match self.next() { - 'R' => bounds.push(self.parse_region()), - '.' => { break; } - c => { - bug!("parse_region_param_def: bad bounds ('{}')", c) - } - } - } - ty::RegionParameterDef { - name: name, - def_id: def_id, - index: index, - bounds: bounds, - } - } - - - fn parse_object_lifetime_default(&mut self) -> ty::ObjectLifetimeDefault<'tcx> { - match self.next() { - 'a' => ty::ObjectLifetimeDefault::Ambiguous, - 'b' => ty::ObjectLifetimeDefault::BaseDefault, - 's' => { - let region = self.parse_region(); - ty::ObjectLifetimeDefault::Specific(region) - } - _ => bug!("parse_object_lifetime_default: bad input") - } - } - fn parse_builtin_bounds(&mut self) -> ty::BuiltinBounds { let mut builtin_bounds = ty::BuiltinBounds::empty(); loop { diff --git a/src/librustc_metadata/tyencode.rs b/src/librustc_metadata/tyencode.rs index 8cd18d1bfc7e8..54b4dc933424e 100644 --- a/src/librustc_metadata/tyencode.rs +++ b/src/librustc_metadata/tyencode.rs @@ -220,22 +220,8 @@ fn enc_mt<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, enc_ty(w, cx, mt.ty); } -fn enc_opt(w: &mut Cursor>, t: Option, enc_f: F) where - F: FnOnce(&mut Cursor>, T), -{ - match t { - None => { - write!(w, "n"); - } - Some(v) => { - write!(w, "s"); - enc_f(w, v); - } - } -} - -pub fn enc_substs<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, - substs: &Substs<'tcx>) { +fn enc_substs<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, + substs: &Substs<'tcx>) { write!(w, "["); for &k in substs.params() { if let Some(ty) = k.as_type() { @@ -251,32 +237,7 @@ pub fn enc_substs<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, write!(w, "]"); } -pub fn enc_generics<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, - generics: &ty::Generics<'tcx>) { - enc_opt(w, generics.parent, |w, def_id| { - write!(w, "{}|", (cx.ds)(cx.tcx, def_id)); - }); - write!(w, "{}|{}[", - generics.parent_regions, - generics.parent_types); - - for r in &generics.regions { - enc_region_param_def(w, cx, r) - } - write!(w, "|"); - for t in &generics.types { - enc_type_param_def(w, cx, t); - } - write!(w, "]"); - - if generics.has_self { - write!(w, "S"); - } else { - write!(w, "N"); - } -} - -pub fn enc_region(w: &mut Cursor>, cx: &ctxt, r: &ty::Region) { +fn enc_region(w: &mut Cursor>, cx: &ctxt, r: &ty::Region) { match *r { ty::ReLateBound(id, br) => { write!(w, "b[{}|", id.depth); @@ -355,8 +316,8 @@ fn enc_bound_region(w: &mut Cursor>, cx: &ctxt, br: ty::BoundRegion) { } } -pub fn enc_trait_ref<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, - s: ty::TraitRef<'tcx>) { +fn enc_trait_ref<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, + s: ty::TraitRef<'tcx>) { write!(w, "{}|", (cx.ds)(cx.tcx, s.def_id)); enc_substs(w, cx, s.substs); } @@ -380,20 +341,13 @@ fn enc_abi(w: &mut Cursor>, abi: Abi) { write!(w, "]"); } -pub fn enc_bare_fn_ty<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, - ft: &ty::BareFnTy<'tcx>) { +fn enc_bare_fn_ty<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, + ft: &ty::BareFnTy<'tcx>) { enc_unsafety(w, ft.unsafety); enc_abi(w, ft.abi); enc_fn_sig(w, cx, &ft.sig); } -pub fn enc_closure_ty<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, - ft: &ty::ClosureTy<'tcx>) { - enc_unsafety(w, ft.unsafety); - enc_fn_sig(w, cx, &ft.sig); - enc_abi(w, ft.abi); -} - fn enc_fn_sig<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, fsig: &ty::PolyFnSig<'tcx>) { write!(w, "["); @@ -422,92 +376,6 @@ fn enc_builtin_bounds(w: &mut Cursor>, _cx: &ctxt, bs: &ty::BuiltinBound write!(w, "."); } -fn enc_type_param_def<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, - v: &ty::TypeParameterDef<'tcx>) { - write!(w, "{}:{}|{}|{}|", - v.name, (cx.ds)(cx.tcx, v.def_id), - v.index, (cx.ds)(cx.tcx, v.default_def_id)); - enc_opt(w, v.default, |w, t| enc_ty(w, cx, t)); - enc_object_lifetime_default(w, cx, v.object_lifetime_default); -} - -fn enc_region_param_def(w: &mut Cursor>, cx: &ctxt, - v: &ty::RegionParameterDef) { - write!(w, "{}:{}|{}|", - v.name, (cx.ds)(cx.tcx, v.def_id), v.index); - for &r in &v.bounds { - write!(w, "R"); - enc_region(w, cx, r); - } - write!(w, "."); -} - -fn enc_object_lifetime_default<'a, 'tcx>(w: &mut Cursor>, - cx: &ctxt<'a, 'tcx>, - default: ty::ObjectLifetimeDefault) -{ - match default { - ty::ObjectLifetimeDefault::Ambiguous => { - write!(w, "a"); - } - ty::ObjectLifetimeDefault::BaseDefault => { - write!(w, "b"); - } - ty::ObjectLifetimeDefault::Specific(r) => { - write!(w, "s"); - enc_region(w, cx, r); - } - } -} - -pub fn enc_predicate<'a, 'tcx>(w: &mut Cursor>, - cx: &ctxt<'a, 'tcx>, - p: &ty::Predicate<'tcx>) -{ - match *p { - ty::Predicate::Trait(ref trait_ref) => { - write!(w, "t"); - enc_trait_ref(w, cx, trait_ref.0.trait_ref); - } - ty::Predicate::Equate(ty::Binder(ty::EquatePredicate(a, b))) => { - write!(w, "e"); - enc_ty(w, cx, a); - enc_ty(w, cx, b); - } - ty::Predicate::RegionOutlives(ty::Binder(ty::OutlivesPredicate(a, b))) => { - write!(w, "r"); - enc_region(w, cx, a); - enc_region(w, cx, b); - } - ty::Predicate::TypeOutlives(ty::Binder(ty::OutlivesPredicate(a, b))) => { - write!(w, "o"); - enc_ty(w, cx, a); - enc_region(w, cx, b); - } - ty::Predicate::Projection(ty::Binder(ref data)) => { - write!(w, "p"); - enc_trait_ref(w, cx, data.projection_ty.trait_ref); - write!(w, "{}|", data.projection_ty.item_name); - enc_ty(w, cx, data.ty); - } - ty::Predicate::WellFormed(data) => { - write!(w, "w"); - enc_ty(w, cx, data); - } - ty::Predicate::ObjectSafe(trait_def_id) => { - write!(w, "O{}|", (cx.ds)(cx.tcx, trait_def_id)); - } - ty::Predicate::ClosureKind(closure_def_id, kind) => { - let kind_char = match kind { - ty::ClosureKind::Fn => 'f', - ty::ClosureKind::FnMut => 'm', - ty::ClosureKind::FnOnce => 'o', - }; - write!(w, "c{}|{}|", (cx.ds)(cx.tcx, closure_def_id), kind_char); - } - } -} - fn enc_existential_projection<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, data: &ty::ExistentialProjection<'tcx>) { From 88c5679c4e0ba0bd21a15eaaf8e5fafcc6bcdafd Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Fri, 2 Sep 2016 11:08:16 +0300 Subject: [PATCH 18/39] rustc_metadata: remove ty{en,de}code and move to auto-derived serialization. --- src/librustc/ty/context.rs | 108 +++-- src/librustc/ty/mod.rs | 40 ++ src/librustc/ty/structural_impls.rs | 13 +- src/librustc/ty/sty.rs | 55 +-- src/librustc_const_eval/check_match.rs | 27 +- src/librustc_metadata/common.rs | 9 +- src/librustc_metadata/decoder.rs | 54 ++- src/librustc_metadata/encoder.rs | 51 ++- src/librustc_metadata/lib.rs | 4 +- src/librustc_metadata/tydecode.rs | 598 ------------------------- src/librustc_metadata/tyencode.rs | 385 ---------------- src/libserialize/collection_impls.rs | 4 +- 12 files changed, 235 insertions(+), 1113 deletions(-) delete mode 100644 src/librustc_metadata/tydecode.rs delete mode 100644 src/librustc_metadata/tyencode.rs diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index bb9e90f891942..338ea6b0dd6d4 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -25,7 +25,7 @@ use middle::stability; use ty::subst::Substs; use traits; use ty::{self, TraitRef, Ty, TypeAndMut}; -use ty::{TyS, TypeVariants}; +use ty::{TyS, TypeVariants, Slice}; use ty::{AdtKind, AdtDef, ClosureSubsts, Region}; use hir::FreevarMap; use ty::{BareFnTy, InferTy, ParamTy, ProjectionTy, TraitObject}; @@ -92,7 +92,7 @@ pub struct CtxtInterners<'tcx> { /// Specifically use a speedy hash algorithm for these hash sets, /// they're accessed quite often. type_: RefCell>>>, - type_list: RefCell]>>>, + type_list: RefCell>>>>, substs: RefCell>>>, bare_fn: RefCell>>>, region: RefCell>>, @@ -847,10 +847,11 @@ impl<'a, 'tcx> Lift<'tcx> for &'a Region { } } -impl<'a, 'tcx> Lift<'tcx> for &'a [Ty<'a>] { - type Lifted = &'tcx [Ty<'tcx>]; - fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<&'tcx [Ty<'tcx>]> { - if let Some(&Interned(list)) = tcx.interners.type_list.borrow().get(*self) { +impl<'a, 'tcx> Lift<'tcx> for &'a Slice> { + type Lifted = &'tcx Slice>; + fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) + -> Option<&'tcx Slice>> { + if let Some(&Interned(list)) = tcx.interners.type_list.borrow().get(&self[..]) { if *self as *const _ == list as *const _ { return Some(list); } @@ -1067,9 +1068,24 @@ impl<'tcx: 'lcx, 'lcx> Borrow> for Interned<'tcx, TyS<'tcx>> } } -impl<'tcx: 'lcx, 'lcx> Borrow<[Ty<'lcx>]> for Interned<'tcx, [Ty<'tcx>]> { +// NB: An Interned> compares and hashes as its elements. +impl<'tcx, T: PartialEq> PartialEq for Interned<'tcx, Slice> { + fn eq(&self, other: &Interned<'tcx, Slice>) -> bool { + self.0[..] == other.0[..] + } +} + +impl<'tcx, T: Eq> Eq for Interned<'tcx, Slice> {} + +impl<'tcx, T: Hash> Hash for Interned<'tcx, Slice> { + fn hash(&self, s: &mut H) { + self.0[..].hash(s) + } +} + +impl<'tcx: 'lcx, 'lcx> Borrow<[Ty<'lcx>]> for Interned<'tcx, Slice>> { fn borrow<'a>(&'a self) -> &'a [Ty<'lcx>] { - self.0 + &self.0[..] } } @@ -1091,32 +1107,23 @@ impl<'tcx> Borrow for Interned<'tcx, Region> { } } -macro_rules! items { ($($item:item)+) => ($($item)+) } -macro_rules! impl_interners { - ($lt_tcx:tt, $($name:ident: $method:ident($alloc:ty, $needs_infer:expr)-> $ty:ty),+) => { - items!($(impl<$lt_tcx> PartialEq for Interned<$lt_tcx, $ty> { - fn eq(&self, other: &Self) -> bool { - self.0 == other.0 - } - } - - impl<$lt_tcx> Eq for Interned<$lt_tcx, $ty> {} - - impl<$lt_tcx> Hash for Interned<$lt_tcx, $ty> { - fn hash(&self, s: &mut H) { - self.0.hash(s) - } - } - +macro_rules! intern_method { + ($lt_tcx:tt, $name:ident: $method:ident($alloc:ty, + $alloc_to_key:expr, + $alloc_to_ret:expr, + $needs_infer:expr) -> $ty:ty) => { impl<'a, 'gcx, $lt_tcx> TyCtxt<'a, 'gcx, $lt_tcx> { pub fn $method(self, v: $alloc) -> &$lt_tcx $ty { - if let Some(i) = self.interners.$name.borrow().get::<$ty>(&v) { - return i.0; - } - if !self.is_global() { - if let Some(i) = self.global_interners.$name.borrow().get::<$ty>(&v) { + { + let key = ($alloc_to_key)(&v); + if let Some(i) = self.interners.$name.borrow().get(key) { return i.0; } + if !self.is_global() { + if let Some(i) = self.global_interners.$name.borrow().get(key) { + return i.0; + } + } } // HACK(eddyb) Depend on flags being accurate to @@ -1127,7 +1134,7 @@ macro_rules! impl_interners { let v = unsafe { mem::transmute(v) }; - let i = self.global_interners.arenas.$name.alloc(v); + let i = ($alloc_to_ret)(self.global_interners.arenas.$name.alloc(v)); self.global_interners.$name.borrow_mut().insert(Interned(i)); return i; } @@ -1141,11 +1148,31 @@ macro_rules! impl_interners { } } - let i = self.interners.arenas.$name.alloc(v); + let i = ($alloc_to_ret)(self.interners.arenas.$name.alloc(v)); self.interners.$name.borrow_mut().insert(Interned(i)); i } - })+); + } + } +} + +macro_rules! direct_interners { + ($lt_tcx:tt, $($name:ident: $method:ident($needs_infer:expr) -> $ty:ty),+) => { + $(impl<$lt_tcx> PartialEq for Interned<$lt_tcx, $ty> { + fn eq(&self, other: &Self) -> bool { + self.0 == other.0 + } + } + + impl<$lt_tcx> Eq for Interned<$lt_tcx, $ty> {} + + impl<$lt_tcx> Hash for Interned<$lt_tcx, $ty> { + fn hash(&self, s: &mut H) { + self.0.hash(s) + } + } + + intern_method!($lt_tcx, $name: $method($ty, |x| x, |x| x, $needs_infer) -> $ty);)+ } } @@ -1153,15 +1180,14 @@ fn keep_local<'tcx, T: ty::TypeFoldable<'tcx>>(x: &T) -> bool { x.has_type_flags(ty::TypeFlags::KEEP_IN_LOCAL_TCX) } -impl_interners!('tcx, - type_list: mk_type_list(Vec>, keep_local) -> [Ty<'tcx>], - substs: mk_substs(Substs<'tcx>, |substs: &Substs| { +direct_interners!('tcx, + substs: mk_substs(|substs: &Substs| { substs.params().iter().any(keep_local) }) -> Substs<'tcx>, - bare_fn: mk_bare_fn(BareFnTy<'tcx>, |fty: &BareFnTy| { + bare_fn: mk_bare_fn(|fty: &BareFnTy| { keep_local(&fty.sig) }) -> BareFnTy<'tcx>, - region: mk_region(Region, |r| { + region: mk_region(|r| { match r { &ty::ReVar(_) | &ty::ReSkolemized(..) => true, _ => false @@ -1169,6 +1195,12 @@ impl_interners!('tcx, }) -> Region ); +intern_method!('tcx, + type_list: mk_type_list(Vec>, Deref::deref, |xs: &[Ty]| -> &Slice { + unsafe { mem::transmute(xs) } + }, keep_local) -> Slice> +); + impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// Create an unsafe fn ty based on a safe fn ty. pub fn safe_to_unsafe_fn_ty(self, bare_fn: &BareFnTy<'tcx>) -> Ty<'tcx> { diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index d4dd8298db3e2..59475b4222635 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -38,6 +38,7 @@ use std::borrow::Cow; use std::cell::Cell; use std::hash::{Hash, Hasher}; use std::iter; +use std::ops::Deref; use std::rc::Rc; use std::slice; use std::vec::IntoIter; @@ -569,6 +570,45 @@ pub type Ty<'tcx> = &'tcx TyS<'tcx>; impl<'tcx> serialize::UseSpecializedEncodable for Ty<'tcx> {} impl<'tcx> serialize::UseSpecializedDecodable for Ty<'tcx> {} +/// A wrapper for slices with the additioanl invariant +/// that the slice is interned and no other slice with +/// the same contents can exist in the same context. +/// This means we can use pointer + length for both +/// equality comparisons and hashing. +#[derive(Debug, RustcEncodable)] +pub struct Slice([T]); + +impl PartialEq for Slice { + #[inline] + fn eq(&self, other: &Slice) -> bool { + (&self.0 as *const [T]) == (&other.0 as *const [T]) + } +} +impl Eq for Slice {} + +impl Hash for Slice { + fn hash(&self, s: &mut H) { + (self.as_ptr(), self.len()).hash(s) + } +} + +impl Deref for Slice { + type Target = [T]; + fn deref(&self) -> &[T] { + &self.0 + } +} + +impl<'a, T> IntoIterator for &'a Slice { + type Item = &'a T; + type IntoIter = <&'a [T] as IntoIterator>::IntoIter; + fn into_iter(self) -> Self::IntoIter { + self[..].iter() + } +} + +impl<'tcx> serialize::UseSpecializedDecodable for &'tcx Slice> {} + /// Upvars do not get their own node-id. Instead, we use the pair of /// the original var id (that is, the root variable that is referenced /// by the upvar) and the id of the closure expression. diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 6c3dabfe113fe..5a87ea1473d98 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -14,7 +14,6 @@ use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; use std::rc::Rc; use syntax::abi; -use syntax::ptr::P; use hir; @@ -437,16 +436,6 @@ impl<'tcx, T:TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder { } } -impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for P<[T]> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - self.iter().map(|t| t.fold_with(folder)).collect() - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.iter().any(|t| t.visit_with(visitor)) - } -} - impl<'tcx> TypeFoldable<'tcx> for ty::TraitObject<'tcx> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { ty::TraitObject { @@ -464,7 +453,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::TraitObject<'tcx> { } } -impl<'tcx> TypeFoldable<'tcx> for &'tcx [Ty<'tcx>] { +impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Slice> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { let tys = self.iter().map(|t| t.fold_with(folder)).collect(); folder.tcx().mk_type_list(tys) diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 0f2ff8a689fa3..302cab0446cd3 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -13,12 +13,12 @@ use hir::def_id::DefId; use middle::region; use ty::subst::Substs; -use ty::{self, AdtDef, ToPredicate, TypeFlags, Ty, TyCtxt, TyS, TypeFoldable}; +use ty::{self, AdtDef, ToPredicate, TypeFlags, Ty, TyCtxt, TypeFoldable}; +use ty::{Slice, TyS}; use util::common::ErrorReported; use collections::enum_set::{self, EnumSet, CLike}; use std::fmt; -use std::mem; use std::ops; use syntax::abi; use syntax::ast::{self, Name}; @@ -31,7 +31,7 @@ use hir; use self::InferTy::*; use self::TypeVariants::*; -#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] pub struct TypeAndMut<'tcx> { pub ty: Ty<'tcx>, pub mutbl: hir::Mutability, @@ -87,7 +87,7 @@ pub enum Issue32330 { // NB: If you change this, you'll probably want to change the corresponding // AST structure in libsyntax/ast.rs as well. -#[derive(Clone, PartialEq, Eq, Hash, Debug)] +#[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] pub enum TypeVariants<'tcx> { /// The primitive boolean type. Written as `bool`. TyBool, @@ -155,7 +155,7 @@ pub enum TypeVariants<'tcx> { TyNever, /// A tuple type. For example, `(i32, bool)`. - TyTuple(&'tcx [Ty<'tcx>]), + TyTuple(&'tcx Slice>), /// The projection of an associated type. For example, /// `>::N`. @@ -252,7 +252,7 @@ pub enum TypeVariants<'tcx> { /// closure C wind up influencing the decisions we ought to make for /// closure C (which would then require fixed point iteration to /// handle). Plus it fixes an ICE. :P -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] pub struct ClosureSubsts<'tcx> { /// Lifetime and type parameters from the enclosing function. /// These are separated out because trans wants to pass them around @@ -262,12 +262,10 @@ pub struct ClosureSubsts<'tcx> { /// The types of the upvars. The list parallels the freevars and /// `upvar_borrows` lists. These are kept distinct so that we can /// easily index into them. - pub upvar_tys: &'tcx [Ty<'tcx>] + pub upvar_tys: &'tcx Slice> } -impl<'tcx> serialize::UseSpecializedDecodable for ClosureSubsts<'tcx> {} - -#[derive(Clone, PartialEq, Eq, Hash)] +#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub struct TraitObject<'tcx> { pub principal: PolyExistentialTraitRef<'tcx>, pub region_bound: &'tcx ty::Region, @@ -330,7 +328,7 @@ impl<'tcx> PolyTraitRef<'tcx> { /// /// The substitutions don't include the erased `Self`, only trait /// type and lifetime parameters (`[X, Y]` and `['a, 'b]` above). -#[derive(Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub struct ExistentialTraitRef<'tcx> { pub def_id: DefId, pub substs: &'tcx Substs<'tcx>, @@ -423,13 +421,15 @@ pub struct ProjectionTy<'tcx> { pub item_name: Name, } -#[derive(Clone, PartialEq, Eq, Hash, Debug)] +#[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] pub struct BareFnTy<'tcx> { pub unsafety: hir::Unsafety, pub abi: abi::Abi, pub sig: PolyFnSig<'tcx>, } +impl<'tcx> serialize::UseSpecializedDecodable for &'tcx BareFnTy<'tcx> {} + #[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub struct ClosureTy<'tcx> { pub unsafety: hir::Unsafety, @@ -467,7 +467,7 @@ impl<'tcx> PolyFnSig<'tcx> { } } -#[derive(Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub struct ParamTy { pub idx: u32, pub name: Name, @@ -654,17 +654,17 @@ pub struct EarlyBoundRegion { pub name: Name, } -#[derive(Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub struct TyVid { pub index: u32, } -#[derive(Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub struct IntVid { pub index: u32 } -#[derive(Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub struct FloatVid { pub index: u32 } @@ -679,7 +679,7 @@ pub struct SkolemizedRegionVid { pub index: u32 } -#[derive(Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub enum InferTy { TyVar(TyVid), IntVar(IntVid), @@ -694,7 +694,7 @@ pub enum InferTy { } /// A `ProjectionPredicate` for an `ExistentialTraitRef`. -#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] pub struct ExistentialProjection<'tcx> { pub trait_ref: ExistentialTraitRef<'tcx>, pub item_name: Name, @@ -739,7 +739,7 @@ impl<'a, 'tcx, 'gcx> PolyExistentialProjection<'tcx> { } } -#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] pub struct BuiltinBounds(EnumSet); impl<'a, 'gcx, 'tcx> BuiltinBounds { @@ -782,12 +782,11 @@ impl<'a> IntoIterator for &'a BuiltinBounds { #[derive(Clone, RustcEncodable, PartialEq, Eq, RustcDecodable, Hash, Debug, Copy)] -#[repr(usize)] pub enum BuiltinBound { - Send, - Sized, - Copy, - Sync, + Send = 0, + Sized = 1, + Copy = 2, + Sync = 3, } impl CLike for BuiltinBound { @@ -795,7 +794,13 @@ impl CLike for BuiltinBound { *self as usize } fn from_usize(v: usize) -> BuiltinBound { - unsafe { mem::transmute(v) } + match v { + 0 => BuiltinBound::Send, + 1 => BuiltinBound::Sized, + 2 => BuiltinBound::Copy, + 3 => BuiltinBound::Sync, + _ => bug!("{} is not a valid BuiltinBound", v) + } } } diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs index dda72ce57b4fa..8af06286189b1 100644 --- a/src/librustc_const_eval/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -26,8 +26,7 @@ use rustc::middle::expr_use_visitor as euv; use rustc::middle::mem_categorization::{cmt}; use rustc::hir::pat_util::*; use rustc::traits::Reveal; -use rustc::ty::*; -use rustc::ty; +use rustc::ty::{self, Ty, TyCtxt}; use std::cmp::Ordering; use std::fmt; use std::iter::{FromIterator, IntoIterator, repeat}; @@ -110,7 +109,7 @@ impl<'a, 'tcx> FromIterator>)>> for Matrix<'a, 'tc //NOTE: appears to be the only place other then InferCtxt to contain a ParamEnv pub struct MatchCheckCtxt<'a, 'tcx: 'a> { pub tcx: TyCtxt<'a, 'tcx, 'tcx>, - pub param_env: ParameterEnvironment<'tcx>, + pub param_env: ty::ParameterEnvironment<'tcx>, } #[derive(Clone, Debug, PartialEq)] @@ -248,7 +247,7 @@ fn check_for_bindings_named_the_same_as_variants(cx: &MatchCheckCtxt, pat: &Pat) if edef.is_enum() { if let Def::Local(..) = cx.tcx.expect_def(p.id) { if edef.variants.iter().any(|variant| { - variant.name == name.node && variant.kind == VariantKind::Unit + variant.name == name.node && variant.kind == ty::VariantKind::Unit }) { let ty_path = cx.tcx.item_path_str(edef.did); let mut err = struct_span_warn!(cx.tcx.sess, p.span, E0170, @@ -579,7 +578,7 @@ fn construct_witness<'a,'tcx>(cx: &MatchCheckCtxt<'a,'tcx>, ctor: &Constructor, ty::TyAdt(adt, _) => { let v = ctor.variant_for_adt(adt); match v.kind { - VariantKind::Struct => { + ty::VariantKind::Struct => { let field_pats: hir::HirVec<_> = v.fields.iter() .zip(pats) .filter(|&(_, ref pat)| pat.node != PatKind::Wild) @@ -594,10 +593,10 @@ fn construct_witness<'a,'tcx>(cx: &MatchCheckCtxt<'a,'tcx>, ctor: &Constructor, let has_more_fields = field_pats.len() < pats_len; PatKind::Struct(def_to_path(cx.tcx, v.did), field_pats, has_more_fields) } - VariantKind::Tuple => { + ty::VariantKind::Tuple => { PatKind::TupleStruct(def_to_path(cx.tcx, v.did), pats.collect(), None) } - VariantKind::Unit => { + ty::VariantKind::Unit => { PatKind::Path(None, def_to_path(cx.tcx, v.did)) } } @@ -639,7 +638,7 @@ fn construct_witness<'a,'tcx>(cx: &MatchCheckCtxt<'a,'tcx>, ctor: &Constructor, impl Constructor { fn variant_for_adt<'tcx, 'container, 'a>(&self, adt: &'a ty::AdtDefData<'tcx, 'container>) - -> &'a VariantDefData<'tcx, 'container> { + -> &'a ty::VariantDefData<'tcx, 'container> { match self { &Variant(vid) => adt.variant_with_id(vid), _ => adt.struct_variant() @@ -878,7 +877,7 @@ fn wrap_pat<'a, 'b, 'tcx>(cx: &MatchCheckCtxt<'b, 'tcx>, let pat_ty = cx.tcx.pat_ty(pat); (pat, Some(match pat.node { PatKind::Binding(hir::BindByRef(..), ..) => { - pat_ty.builtin_deref(false, NoPreference).unwrap().ty + pat_ty.builtin_deref(false, ty::NoPreference).unwrap().ty } _ => pat_ty })) @@ -1068,7 +1067,7 @@ fn check_fn(cx: &mut MatchCheckCtxt, fn_id: NodeId) { match kind { FnKind::Closure(_) => {} - _ => cx.param_env = ParameterEnvironment::for_item(cx.tcx, fn_id), + _ => cx.param_env = ty::ParameterEnvironment::for_item(cx.tcx, fn_id), } intravisit::walk_fn(cx, kind, decl, body, sp, fn_id); @@ -1187,17 +1186,17 @@ impl<'a, 'gcx, 'tcx> Delegate<'tcx> for MutationChecker<'a, 'gcx> { _: NodeId, span: Span, _: cmt, - _: &'tcx Region, - kind: BorrowKind, + _: &'tcx ty::Region, + kind:ty:: BorrowKind, _: LoanCause) { match kind { - MutBorrow => { + ty::MutBorrow => { struct_span_err!(self.cx.tcx.sess, span, E0301, "cannot mutably borrow in a pattern guard") .span_label(span, &format!("borrowed mutably in pattern guard")) .emit(); } - ImmBorrow | UniqueImmBorrow => {} + ty::ImmBorrow | ty::UniqueImmBorrow => {} } } fn decl_without_init(&mut self, _: NodeId, _: Span) {} diff --git a/src/librustc_metadata/common.rs b/src/librustc_metadata/common.rs index 3b63ee6b5fa89..123ed11a7a513 100644 --- a/src/librustc_metadata/common.rs +++ b/src/librustc_metadata/common.rs @@ -10,9 +10,7 @@ #![allow(non_camel_case_types, non_upper_case_globals)] -pub const tag_opaque: usize = 0x00; - -// GAP 0x01...0x19 +// GAP 0x00...0x19 pub const tag_items: usize = 0x100; // top-level only @@ -214,3 +212,8 @@ pub const tag_macro_derive_registrar: usize = 0x115; // NB: increment this if you change the format of metadata such that // rustc_version can't be found. pub const metadata_encoding_version : &'static [u8] = &[b'r', b'u', b's', b't', 0, 0, 0, 2]; + +/// The shorthand encoding of `Ty` uses `TypeVariants`' variant `usize` +/// and is offset by this value so it never matches a real variant. +/// This offset is also chosen so that the first byte is never < 0x80. +pub const TYPE_SHORTHAND_OFFSET: usize = 0x80; diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index d3c04874a08ef..0118cacad182e 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -20,7 +20,6 @@ use common::*; use def_key; use encoder::def_to_u64; use index; -use tydecode::TyDecoder; use rustc::hir::def_id::CRATE_DEF_INDEX; use rustc::hir::svh::Svh; @@ -45,13 +44,14 @@ use rustc_const_math::ConstInt; use rustc::mir::repr::Mir; use std::io; +use std::mem; use std::rc::Rc; use std::str; use std::u32; use rbml::reader; use rbml; -use rustc_serialize::{Decodable, SpecializedDecoder, opaque}; +use rustc_serialize::{Decodable, Decoder, SpecializedDecoder, opaque}; use rustc_serialize as serialize; use syntax::attr; use syntax::parse::token; @@ -233,35 +233,53 @@ impl<'a, 'tcx> SpecializedDecoder for DecodeContext<'a, 'tcx> { impl<'a, 'tcx> SpecializedDecoder> for DecodeContext<'a, 'tcx> { fn specialized_decode(&mut self) -> Result, Self::Error> { - let pos = self.opaque.position(); - let doc = rbml::Doc::at(self.opaque.data, pos); - self.opaque.advance(doc.end - pos); - Ok(TyDecoder::with_doc(self.tcx(), self.cdata().cnum, doc, - &mut |d| translate_def_id(self.cdata(), d)) - .parse_ty()) + let tcx = self.tcx(); + + // Handle shorthands first, if we have an usize > 0x80. + if self.opaque.data[self.opaque.position()] & 0x80 != 0 { + let pos = self.read_usize()?; + assert!(pos >= TYPE_SHORTHAND_OFFSET); + let key = ty::CReaderCacheKey { + cnum: self.cdata().cnum, + pos: pos - TYPE_SHORTHAND_OFFSET + }; + if let Some(ty) = tcx.rcache.borrow().get(&key).cloned() { + return Ok(ty); + } + + let new = opaque::Decoder::new(self.opaque.data, key.pos); + let old = mem::replace(&mut self.opaque, new); + let ty = Ty::decode(self)?; + self.opaque = old; + tcx.rcache.borrow_mut().insert(key, ty); + return Ok(ty); + } + + Ok(tcx.mk_ty(ty::TypeVariants::decode(self)?)) } } impl<'a, 'tcx> SpecializedDecoder<&'tcx Substs<'tcx>> for DecodeContext<'a, 'tcx> { fn specialized_decode(&mut self) -> Result<&'tcx Substs<'tcx>, Self::Error> { - let substs = Substs::decode(self)?; - Ok(self.tcx().mk_substs(substs)) + Ok(self.tcx().mk_substs(Decodable::decode(self)?)) } } impl<'a, 'tcx> SpecializedDecoder<&'tcx ty::Region> for DecodeContext<'a, 'tcx> { fn specialized_decode(&mut self) -> Result<&'tcx ty::Region, Self::Error> { - let r = ty::Region::decode(self)?; - Ok(self.tcx().mk_region(r)) + Ok(self.tcx().mk_region(Decodable::decode(self)?)) } } -impl<'a, 'tcx> SpecializedDecoder> for DecodeContext<'a, 'tcx> { - fn specialized_decode(&mut self) -> Result, Self::Error> { - Ok(ty::ClosureSubsts { - func_substs: Decodable::decode(self)?, - upvar_tys: self.tcx().mk_type_list(Decodable::decode(self)?) - }) +impl<'a, 'tcx> SpecializedDecoder<&'tcx ty::Slice>> for DecodeContext<'a, 'tcx> { + fn specialized_decode(&mut self) -> Result<&'tcx ty::Slice>, Self::Error> { + Ok(self.tcx().mk_type_list(Decodable::decode(self)?)) + } +} + +impl<'a, 'tcx> SpecializedDecoder<&'tcx ty::BareFnTy<'tcx>> for DecodeContext<'a, 'tcx> { + fn specialized_decode(&mut self) -> Result<&'tcx ty::BareFnTy<'tcx>, Self::Error> { + Ok(self.tcx().mk_bare_fn(Decodable::decode(self)?)) } } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index dcc3d13631eba..e414275f8b425 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -18,7 +18,6 @@ use common::*; use cstore; use decoder; use def_key; -use tyencode; use index::{self, IndexData}; use middle::cstore::{InlinedItemRef, LinkMeta}; @@ -34,8 +33,10 @@ use rustc::mir::mir_map::MirMap; use rustc::session::config::{self, PanicStrategy, CrateTypeRustcMacro}; use rustc::util::nodemap::{FnvHashMap, NodeSet}; -use rustc_serialize::{Encodable, SpecializedEncoder, opaque}; +use rustc_serialize::{Encodable, Encoder, SpecializedEncoder, opaque}; use rustc_serialize as serialize; +use std::cell::RefCell; +use std::intrinsics; use std::io::prelude::*; use std::io::Cursor; use std::ops::{Deref, DerefMut}; @@ -55,14 +56,14 @@ use rustc::hir::map::DefKey; use super::index_builder::{FromId, IndexBuilder, ItemContentBuilder, Untracked, XRef}; pub struct EncodeContext<'a, 'tcx: 'a> { - pub rbml_w: rbml::writer::Encoder<'a>, + rbml_w: rbml::writer::Encoder<'a>, pub tcx: TyCtxt<'a, 'tcx, 'tcx>, - pub reexports: &'a def::ExportMap, - pub link_meta: &'a LinkMeta, - pub cstore: &'a cstore::CStore, - pub type_abbrevs: &'a tyencode::abbrev_map<'tcx>, - pub reachable: &'a NodeSet, - pub mir_map: &'a MirMap<'tcx>, + reexports: &'a def::ExportMap, + link_meta: &'a LinkMeta, + cstore: &'a cstore::CStore, + type_shorthands: RefCell, usize>>, + reachable: &'a NodeSet, + mir_map: &'a MirMap<'tcx>, } impl<'a, 'tcx> Deref for EncodeContext<'a, 'tcx> { @@ -116,12 +117,32 @@ impl<'a, 'tcx> serialize::Encoder for ::encoder::EncodeContext<'a, 'tcx> { impl<'a, 'tcx> SpecializedEncoder> for EncodeContext<'a, 'tcx> { fn specialized_encode(&mut self, ty: &Ty<'tcx>) -> Result<(), Self::Error> { - let cx = self.ty_str_ctxt(); + let existing_shorthand = self.type_shorthands.borrow().get(ty).cloned(); + if let Some(shorthand) = existing_shorthand { + return self.emit_usize(shorthand); + } + + let start = self.mark_stable_position(); + ty.sty.encode(self)?; + let len = self.mark_stable_position() - start; + + // The shorthand encoding uses the same usize as the + // discriminant, with an offset so they can't conflict. + let discriminant = unsafe { intrinsics::discriminant_value(&ty.sty) }; + assert!(discriminant < TYPE_SHORTHAND_OFFSET as u64); + let shorthand = start + TYPE_SHORTHAND_OFFSET; + + // Get the number of bits that leb128 could fit + // in the same space as the fully encoded type. + let leb128_bits = len * 7; - self.start_tag(tag_opaque)?; - tyencode::enc_ty(&mut self.rbml_w.opaque.cursor, &cx, ty); - self.mark_stable_position(); - self.end_tag() + // Check that the shorthand is a not longer than the + // full encoding itself, i.e. it's an obvious win. + if leb128_bits >= 64 || (shorthand as u64) < (1 << leb128_bits) { + self.type_shorthands.borrow_mut().insert(*ty, shorthand); + } + + Ok(()) } } @@ -1742,7 +1763,7 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, cstore: cstore, reachable: reachable, mir_map: mir_map, - type_abbrevs: &Default::default(), + type_shorthands: Default::default(), }); // RBML compacts the encoded bytes whenever appropriate, diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs index 7205a88618fcc..e5f7aab38c364 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -17,9 +17,9 @@ html_root_url = "https://doc.rust-lang.org/nightly/")] #![cfg_attr(not(stage0), deny(warnings))] +#![feature(core_intrinsics)] #![feature(box_patterns)] #![feature(dotdot_in_tuple_patterns)] -#![feature(enumset)] #![feature(question_mark)] #![feature(quote)] #![feature(rustc_diagnostic_macros)] @@ -63,8 +63,6 @@ pub mod diagnostics; pub mod astencode; pub mod common; pub mod def_key; -pub mod tyencode; -pub mod tydecode; pub mod encoder; mod index_builder; pub mod decoder; diff --git a/src/librustc_metadata/tydecode.rs b/src/librustc_metadata/tydecode.rs deleted file mode 100644 index ccc4894fcdda2..0000000000000 --- a/src/librustc_metadata/tydecode.rs +++ /dev/null @@ -1,598 +0,0 @@ -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - -// Type decoding - -// tjc note: Would be great to have a `match check` macro equivalent -// for some of these - -#![allow(non_camel_case_types)] - -use rustc::hir; - -use rustc::hir::def_id::{CrateNum, DefId, DefIndex}; -use middle::region; -use rustc::ty::subst::{Kind, Substs}; -use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; - -use rbml; -use rustc_serialize::leb128; -use std::str; -use syntax::abi; -use syntax::ast; -use syntax::parse::token; - -// Compact string representation for Ty values. API TyStr & -// parse_from_str. Extra parameters are for converting to/from def_ids in the -// data buffer. Whatever format you choose should not contain pipe characters. - -pub type DefIdConvert<'a> = &'a mut FnMut(DefId) -> DefId; - -pub struct TyDecoder<'a, 'tcx: 'a> { - data: &'a [u8], - krate: CrateNum, - pos: usize, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - conv_def_id: DefIdConvert<'a>, -} - -impl<'a,'tcx> TyDecoder<'a,'tcx> { - pub fn with_doc(tcx: TyCtxt<'a, 'tcx, 'tcx>, - crate_num: CrateNum, - doc: rbml::Doc<'a>, - conv: DefIdConvert<'a>) - -> TyDecoder<'a,'tcx> { - TyDecoder::new(doc.data, crate_num, doc.start, tcx, conv) - } - - pub fn new(data: &'a [u8], - crate_num: CrateNum, - pos: usize, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - conv: DefIdConvert<'a>) - -> TyDecoder<'a, 'tcx> { - TyDecoder { - data: data, - krate: crate_num, - pos: pos, - tcx: tcx, - conv_def_id: conv, - } - } - - pub fn position(&self) -> usize { - self.pos - } - - fn peek(&self) -> char { - self.data[self.pos] as char - } - - fn next(&mut self) -> char { - let ch = self.data[self.pos] as char; - self.pos = self.pos + 1; - return ch; - } - - fn next_byte(&mut self) -> u8 { - let b = self.data[self.pos]; - self.pos = self.pos + 1; - return b; - } - - fn scan(&mut self, mut is_last: F) -> &'a [u8] - where F: FnMut(char) -> bool, - { - let start_pos = self.pos; - debug!("scan: '{}' (start)", self.data[self.pos] as char); - while !is_last(self.data[self.pos] as char) { - self.pos += 1; - debug!("scan: '{}'", self.data[self.pos] as char); - } - let end_pos = self.pos; - self.pos += 1; - return &self.data[start_pos..end_pos]; - } - - fn parse_vuint(&mut self) -> usize { - let (value, bytes_read) = leb128::read_unsigned_leb128(self.data, - self.pos); - self.pos += bytes_read; - value as usize - } - - fn parse_size(&mut self) -> Option { - assert_eq!(self.next(), '/'); - - if self.peek() == '|' { - assert_eq!(self.next(), '|'); - None - } else { - let n = self.parse_uint(); - assert_eq!(self.next(), '|'); - Some(n) - } - } - - fn parse_substs(&mut self) -> &'tcx Substs<'tcx> { - let mut params = vec![]; - assert_eq!(self.next(), '['); - while self.peek() != ']' { - let k = match self.next() { - 'r' => Kind::from(self.parse_region()), - 't' => Kind::from(self.parse_ty()), - _ => bug!() - }; - params.push(k); - } - assert_eq!(self.next(), ']'); - - Substs::new(self.tcx, params) - } - - fn parse_bound_region(&mut self) -> ty::BoundRegion { - match self.next() { - 'a' => { - let id = self.parse_u32(); - assert_eq!(self.next(), '|'); - ty::BrAnon(id) - } - '[' => { - let def = self.parse_def(); - let name = token::intern(&self.parse_str('|')); - let issue32330 = match self.next() { - 'n' => { - assert_eq!(self.next(), ']'); - ty::Issue32330::WontChange - } - 'y' => { - ty::Issue32330::WillChange { - fn_def_id: self.parse_def(), - region_name: token::intern(&self.parse_str(']')), - } - } - c => panic!("expected n or y not {}", c) - }; - ty::BrNamed(def, name, issue32330) - } - 'f' => { - let id = self.parse_u32(); - assert_eq!(self.next(), '|'); - ty::BrFresh(id) - } - 'e' => ty::BrEnv, - _ => bug!("parse_bound_region: bad input") - } - } - - fn parse_region(&mut self) -> &'tcx ty::Region { - self.tcx.mk_region(match self.next() { - 'b' => { - assert_eq!(self.next(), '['); - let id = ty::DebruijnIndex::new(self.parse_u32()); - assert_eq!(self.next(), '|'); - let br = self.parse_bound_region(); - assert_eq!(self.next(), ']'); - ty::ReLateBound(id, br) - } - 'B' => { - assert_eq!(self.next(), '['); - let index = self.parse_u32(); - assert_eq!(self.next(), '|'); - let name = token::intern(&self.parse_str(']')); - ty::ReEarlyBound(ty::EarlyBoundRegion { - index: index, - name: name - }) - } - 'f' => { - assert_eq!(self.next(), '['); - let scope = self.parse_scope(); - assert_eq!(self.next(), '|'); - let br = self.parse_bound_region(); - assert_eq!(self.next(), ']'); - ty::ReFree(ty::FreeRegion { scope: scope, - bound_region: br}) - } - 's' => { - let scope = self.parse_scope(); - assert_eq!(self.next(), '|'); - ty::ReScope(scope) - } - 't' => ty::ReStatic, - 'e' => ty::ReEmpty, - 'E' => ty::ReErased, - _ => bug!("parse_region: bad input") - }) - } - - fn parse_scope(&mut self) -> region::CodeExtent { - self.tcx.region_maps.bogus_code_extent(match self.next() { - // This creates scopes with the wrong NodeId. This isn't - // actually a problem because scopes only exist *within* - // functions, and functions aren't loaded until trans which - // doesn't care about regions. - // - // May still be worth fixing though. - 'C' => { - assert_eq!(self.next(), '['); - let fn_id = ast::NodeId::new(self.parse_uint()); - assert_eq!(self.next(), '|'); - let body_id = ast::NodeId::new(self.parse_uint()); - assert_eq!(self.next(), ']'); - region::CodeExtentData::CallSiteScope { - fn_id: fn_id, body_id: body_id - } - } - // This creates scopes with the wrong NodeId. (See note above.) - 'P' => { - assert_eq!(self.next(), '['); - let fn_id = ast::NodeId::new(self.parse_uint()); - assert_eq!(self.next(), '|'); - let body_id = ast::NodeId::new(self.parse_uint()); - assert_eq!(self.next(), ']'); - region::CodeExtentData::ParameterScope { - fn_id: fn_id, body_id: body_id - } - } - 'M' => { - let node_id = ast::NodeId::new(self.parse_uint()); - region::CodeExtentData::Misc(node_id) - } - 'D' => { - let node_id = ast::NodeId::new(self.parse_uint()); - region::CodeExtentData::DestructionScope(node_id) - } - 'B' => { - assert_eq!(self.next(), '['); - let node_id = ast::NodeId::new(self.parse_uint()); - assert_eq!(self.next(), '|'); - let first_stmt_index = self.parse_u32(); - assert_eq!(self.next(), ']'); - let block_remainder = region::BlockRemainder { - block: node_id, first_statement_index: first_stmt_index, - }; - region::CodeExtentData::Remainder(block_remainder) - } - _ => bug!("parse_scope: bad input") - }) - } - - fn parse_str(&mut self, term: char) -> String { - let mut result = String::new(); - while self.peek() != term { - unsafe { - result.as_mut_vec().extend_from_slice(&[self.next_byte()]) - } - } - self.next(); - result - } - - fn parse_trait_ref(&mut self) -> ty::TraitRef<'tcx> { - ty::TraitRef { - def_id: self.parse_def(), - substs: self.parse_substs() - } - } - - fn parse_existential_trait_ref(&mut self) -> ty::ExistentialTraitRef<'tcx> { - ty::ExistentialTraitRef { - def_id: self.parse_def(), - substs: self.parse_substs() - } - } - - pub fn parse_ty(&mut self) -> Ty<'tcx> { - let tcx = self.tcx; - match self.next() { - 'b' => return tcx.types.bool, - '!' => return tcx.types.never, - 'i' => { /* eat the s of is */ self.next(); return tcx.types.isize }, - 'u' => { /* eat the s of us */ self.next(); return tcx.types.usize }, - 'M' => { - match self.next() { - 'b' => return tcx.types.u8, - 'w' => return tcx.types.u16, - 'l' => return tcx.types.u32, - 'd' => return tcx.types.u64, - 'B' => return tcx.types.i8, - 'W' => return tcx.types.i16, - 'L' => return tcx.types.i32, - 'D' => return tcx.types.i64, - 'f' => return tcx.types.f32, - 'F' => return tcx.types.f64, - _ => bug!("parse_ty: bad numeric type") - } - } - 'c' => return tcx.types.char, - 'x' => { - assert_eq!(self.next(), '['); - let trait_ref = ty::Binder(self.parse_existential_trait_ref()); - let builtin_bounds = self.parse_builtin_bounds(); - let region_bound = self.parse_region(); - let mut projection_bounds = Vec::new(); - - loop { - match self.next() { - 'P' => { - let bound = self.parse_existential_projection(); - projection_bounds.push(ty::Binder(bound)); - } - '.' => { break; } - c => { - bug!("parse_bounds: bad bounds ('{}')", c) - } - } - } - assert_eq!(self.next(), ']'); - return tcx.mk_trait(ty::TraitObject { - principal: trait_ref, - region_bound: region_bound, - builtin_bounds: builtin_bounds, - projection_bounds: projection_bounds - }); - } - 'p' => { - assert_eq!(self.next(), '['); - let index = self.parse_u32(); - assert_eq!(self.next(), '|'); - let name = token::intern(&self.parse_str(']')); - return tcx.mk_param(index, name); - } - '~' => return tcx.mk_box(self.parse_ty()), - '*' => return tcx.mk_ptr(self.parse_mt()), - '&' => { - return tcx.mk_ref(self.parse_region(), self.parse_mt()); - } - 'V' => { - let t = self.parse_ty(); - return match self.parse_size() { - Some(n) => tcx.mk_array(t, n), - None => tcx.mk_slice(t) - }; - } - 'v' => { - return tcx.mk_str(); - } - 'T' => { - assert_eq!(self.next(), '['); - let mut params = Vec::new(); - while self.peek() != ']' { params.push(self.parse_ty()); } - self.pos = self.pos + 1; - return tcx.mk_tup(params); - } - 'F' => { - let def_id = self.parse_def(); - let substs = self.parse_substs(); - return tcx.mk_fn_def(def_id, substs, self.parse_bare_fn_ty()); - } - 'G' => { - return tcx.mk_fn_ptr(self.parse_bare_fn_ty()); - } - '#' => { - // This is a hacky little caching scheme. The idea is that if we encode - // the same type twice, the second (and third, and fourth...) time we will - // just write `#123`, where `123` is the offset in the metadata of the - // first appearance. Now when we are *decoding*, if we see a `#123`, we - // can first check a cache (`tcx.rcache`) for that offset. If we find something, - // we return it (modulo closure types, see below). But if not, then we - // jump to offset 123 and read the type from there. - - let pos = self.parse_vuint(); - let key = ty::CReaderCacheKey { cnum: self.krate, pos: pos }; - if let Some(tt) = tcx.rcache.borrow().get(&key).cloned() { - // If there is a closure buried in the type some where, then we - // need to re-convert any def ids (see case 'k', below). That means - // we can't reuse the cached version. - if !tt.has_closure_types() { - return tt; - } - } - - let mut substate = TyDecoder::new(self.data, - self.krate, - pos, - self.tcx, - self.conv_def_id); - let tt = substate.parse_ty(); - tcx.rcache.borrow_mut().insert(key, tt); - return tt; - } - '\"' => { - let _ = self.parse_def(); - let inner = self.parse_ty(); - inner - } - 'a' => { - assert_eq!(self.next(), '['); - let did = self.parse_def(); - let substs = self.parse_substs(); - assert_eq!(self.next(), ']'); - let def = self.tcx.lookup_adt_def(did); - return self.tcx.mk_adt(def, substs); - } - 'k' => { - assert_eq!(self.next(), '['); - let did = self.parse_def(); - let substs = self.parse_substs(); - let mut tys = vec![]; - while self.peek() != '.' { - tys.push(self.parse_ty()); - } - assert_eq!(self.next(), '.'); - assert_eq!(self.next(), ']'); - return self.tcx.mk_closure(did, substs, tys); - } - 'P' => { - assert_eq!(self.next(), '['); - let trait_ref = self.parse_trait_ref(); - let name = token::intern(&self.parse_str(']')); - return tcx.mk_projection(trait_ref, name); - } - 'A' => { - assert_eq!(self.next(), '['); - let def_id = self.parse_def(); - let substs = self.parse_substs(); - assert_eq!(self.next(), ']'); - return self.tcx.mk_anon(def_id, substs); - } - 'e' => { - return tcx.types.err; - } - c => { bug!("unexpected char in type string: {}", c);} - } - } - - fn parse_mutability(&mut self) -> hir::Mutability { - match self.peek() { - 'm' => { self.next(); hir::MutMutable } - _ => { hir::MutImmutable } - } - } - - fn parse_mt(&mut self) -> ty::TypeAndMut<'tcx> { - let m = self.parse_mutability(); - ty::TypeAndMut { ty: self.parse_ty(), mutbl: m } - } - - fn parse_def(&mut self) -> DefId { - let def_id = parse_defid(self.scan(|c| c == '|')); - return (self.conv_def_id)(def_id); - } - - fn parse_uint(&mut self) -> usize { - let mut n = 0; - loop { - let cur = self.peek(); - if cur < '0' || cur > '9' { return n; } - self.pos = self.pos + 1; - n *= 10; - n += (cur as usize) - ('0' as usize); - }; - } - - fn parse_u32(&mut self) -> u32 { - let n = self.parse_uint(); - let m = n as u32; - assert_eq!(m as usize, n); - m - } - - fn parse_abi_set(&mut self) -> abi::Abi { - assert_eq!(self.next(), '['); - let bytes = self.scan(|c| c == ']'); - let abi_str = str::from_utf8(bytes).unwrap(); - abi::lookup(&abi_str[..]).expect(abi_str) - } - - fn parse_bare_fn_ty(&mut self) -> &'tcx ty::BareFnTy<'tcx> { - let unsafety = parse_unsafety(self.next()); - let abi = self.parse_abi_set(); - let sig = self.parse_sig(); - self.tcx.mk_bare_fn(ty::BareFnTy { - unsafety: unsafety, - abi: abi, - sig: sig - }) - } - - fn parse_sig(&mut self) -> ty::PolyFnSig<'tcx> { - assert_eq!(self.next(), '['); - let mut inputs = Vec::new(); - while self.peek() != ']' { - inputs.push(self.parse_ty()); - } - self.pos += 1; // eat the ']' - let variadic = match self.next() { - 'V' => true, - 'N' => false, - r => bug!("bad variadic: {}", r), - }; - let output = self.parse_ty(); - ty::Binder(ty::FnSig {inputs: inputs, - output: output, - variadic: variadic}) - } - - fn parse_existential_projection(&mut self) -> ty::ExistentialProjection<'tcx> { - ty::ExistentialProjection { - trait_ref: self.parse_existential_trait_ref(), - item_name: token::intern(&self.parse_str('|')), - ty: self.parse_ty(), - } - } - - fn parse_builtin_bounds(&mut self) -> ty::BuiltinBounds { - let mut builtin_bounds = ty::BuiltinBounds::empty(); - loop { - match self.next() { - 'S' => { - builtin_bounds.insert(ty::BoundSend); - } - 'Z' => { - builtin_bounds.insert(ty::BoundSized); - } - 'P' => { - builtin_bounds.insert(ty::BoundCopy); - } - 'T' => { - builtin_bounds.insert(ty::BoundSync); - } - '.' => { - return builtin_bounds; - } - c => { - bug!("parse_bounds: bad builtin bounds ('{}')", c) - } - } - } - } -} - -// Rust metadata parsing -fn parse_defid(buf: &[u8]) -> DefId { - let mut colon_idx = 0; - let len = buf.len(); - while colon_idx < len && buf[colon_idx] != ':' as u8 { colon_idx += 1; } - if colon_idx == len { - error!("didn't find ':' when parsing def id"); - bug!(); - } - - let crate_part = &buf[0..colon_idx]; - let def_part = &buf[colon_idx + 1..len]; - - let crate_num = match str::from_utf8(crate_part).ok().and_then(|s| { - s.parse::().ok() - }) { - Some(cn) => CrateNum::new(cn), - None => bug!("internal error: parse_defid: crate number expected, found {:?}", - crate_part) - }; - let def_num = match str::from_utf8(def_part).ok().and_then(|s| { - s.parse::().ok() - }) { - Some(dn) => dn, - None => bug!("internal error: parse_defid: id expected, found {:?}", - def_part) - }; - let index = DefIndex::new(def_num); - DefId { krate: crate_num, index: index } -} - -fn parse_unsafety(c: char) -> hir::Unsafety { - match c { - 'u' => hir::Unsafety::Unsafe, - 'n' => hir::Unsafety::Normal, - _ => bug!("parse_unsafety: bad unsafety {}", c) - } -} diff --git a/src/librustc_metadata/tyencode.rs b/src/librustc_metadata/tyencode.rs deleted file mode 100644 index 54b4dc933424e..0000000000000 --- a/src/librustc_metadata/tyencode.rs +++ /dev/null @@ -1,385 +0,0 @@ -// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Type encoding - -#![allow(unused_must_use)] // as with encoding, everything is a no-fail MemWriter -#![allow(non_camel_case_types)] - -use std::cell::RefCell; -use std::io::Cursor; -use std::io::prelude::*; - -use rustc::hir::def_id::DefId; -use middle::region; -use rustc::ty::subst::Substs; -use rustc::ty::{self, Ty, TyCtxt}; -use rustc::util::nodemap::FnvHashMap; - -use rustc::hir; - -use syntax::abi::Abi; -use syntax::ast; - -use rustc_serialize::leb128; -use encoder; - -pub struct ctxt<'a, 'tcx: 'a> { - // Def -> str Callback: - pub ds: for<'b> fn(TyCtxt<'b, 'tcx, 'tcx>, DefId) -> String, - // The type context. - pub tcx: TyCtxt<'a, 'tcx, 'tcx>, - pub abbrevs: &'a abbrev_map<'tcx> -} - -impl<'a, 'tcx> encoder::EncodeContext<'a, 'tcx> { - pub fn ty_str_ctxt(&self) -> ctxt<'a, 'tcx> { - ctxt { - ds: encoder::def_to_string, - tcx: self.tcx, - abbrevs: self.type_abbrevs - } - } -} - -// Compact string representation for Ty values. API TyStr & parse_from_str. -// Extra parameters are for converting to/from def_ids in the string rep. -// Whatever format you choose should not contain pipe characters. -pub struct ty_abbrev { - s: Vec -} - -pub type abbrev_map<'tcx> = RefCell, ty_abbrev>>; - -pub fn enc_ty<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, t: Ty<'tcx>) { - if let Some(a) = cx.abbrevs.borrow_mut().get(&t) { - w.write_all(&a.s); - return; - } - - let pos = w.position(); - - match t.sty { - ty::TyBool => { write!(w, "b"); } - ty::TyChar => { write!(w, "c"); } - ty::TyNever => { write!(w, "!"); } - ty::TyInt(t) => { - match t { - ast::IntTy::Is => write!(w, "is"), - ast::IntTy::I8 => write!(w, "MB"), - ast::IntTy::I16 => write!(w, "MW"), - ast::IntTy::I32 => write!(w, "ML"), - ast::IntTy::I64 => write!(w, "MD") - }; - } - ty::TyUint(t) => { - match t { - ast::UintTy::Us => write!(w, "us"), - ast::UintTy::U8 => write!(w, "Mb"), - ast::UintTy::U16 => write!(w, "Mw"), - ast::UintTy::U32 => write!(w, "Ml"), - ast::UintTy::U64 => write!(w, "Md") - }; - } - ty::TyFloat(t) => { - match t { - ast::FloatTy::F32 => write!(w, "Mf"), - ast::FloatTy::F64 => write!(w, "MF"), - }; - } - ty::TyTrait(ref obj) => { - write!(w, "x["); - enc_existential_trait_ref(w, cx, obj.principal.0); - enc_builtin_bounds(w, cx, &obj.builtin_bounds); - - enc_region(w, cx, obj.region_bound); - - for tp in &obj.projection_bounds { - write!(w, "P"); - enc_existential_projection(w, cx, &tp.0); - } - - write!(w, "."); - write!(w, "]"); - } - ty::TyTuple(ts) => { - write!(w, "T["); - for t in ts { enc_ty(w, cx, *t); } - write!(w, "]"); - } - ty::TyBox(typ) => { write!(w, "~"); enc_ty(w, cx, typ); } - ty::TyRawPtr(mt) => { write!(w, "*"); enc_mt(w, cx, mt); } - ty::TyRef(r, mt) => { - write!(w, "&"); - enc_region(w, cx, r); - enc_mt(w, cx, mt); - } - ty::TyArray(t, sz) => { - write!(w, "V"); - enc_ty(w, cx, t); - write!(w, "/{}|", sz); - } - ty::TySlice(t) => { - write!(w, "V"); - enc_ty(w, cx, t); - write!(w, "/|"); - } - ty::TyStr => { - write!(w, "v"); - } - ty::TyFnDef(def_id, substs, f) => { - write!(w, "F"); - write!(w, "{}|", (cx.ds)(cx.tcx, def_id)); - enc_substs(w, cx, substs); - enc_bare_fn_ty(w, cx, f); - } - ty::TyFnPtr(f) => { - write!(w, "G"); - enc_bare_fn_ty(w, cx, f); - } - ty::TyInfer(_) => { - bug!("cannot encode inference variable types"); - } - ty::TyParam(p) => { - write!(w, "p[{}|{}]", p.idx, p.name); - } - ty::TyAdt(def, substs) => { - write!(w, "a[{}|", (cx.ds)(cx.tcx, def.did)); - enc_substs(w, cx, substs); - write!(w, "]"); - } - ty::TyClosure(def, substs) => { - write!(w, "k[{}|", (cx.ds)(cx.tcx, def)); - enc_substs(w, cx, substs.func_substs); - for ty in substs.upvar_tys { - enc_ty(w, cx, ty); - } - write!(w, "."); - write!(w, "]"); - } - ty::TyProjection(ref data) => { - write!(w, "P["); - enc_trait_ref(w, cx, data.trait_ref); - write!(w, "{}]", data.item_name); - } - ty::TyAnon(def_id, substs) => { - write!(w, "A[{}|", (cx.ds)(cx.tcx, def_id)); - enc_substs(w, cx, substs); - write!(w, "]"); - } - ty::TyError => { - write!(w, "e"); - } - } - - let end = w.position(); - let len = end - pos; - - let mut abbrev = Cursor::new(Vec::with_capacity(16)); - abbrev.write_all(b"#"); - { - let start_position = abbrev.position() as usize; - let meta_start = 8 + ::common::metadata_encoding_version.len() as u64; - let bytes_written = leb128::write_unsigned_leb128(abbrev.get_mut(), - start_position, - pos - meta_start); - abbrev.set_position((start_position + bytes_written) as u64); - } - - cx.abbrevs.borrow_mut().insert(t, ty_abbrev { - s: if abbrev.position() < len { - abbrev.get_ref()[..abbrev.position() as usize].to_owned() - } else { - // if the abbreviation is longer than the real type, - // don't use #-notation. However, insert it here so - // other won't have to `mark_stable_position` - w.get_ref()[pos as usize .. end as usize].to_owned() - } - }); -} - -fn enc_mutability(w: &mut Cursor>, mt: hir::Mutability) { - match mt { - hir::MutImmutable => (), - hir::MutMutable => { - write!(w, "m"); - } - }; -} - -fn enc_mt<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, - mt: ty::TypeAndMut<'tcx>) { - enc_mutability(w, mt.mutbl); - enc_ty(w, cx, mt.ty); -} - -fn enc_substs<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, - substs: &Substs<'tcx>) { - write!(w, "["); - for &k in substs.params() { - if let Some(ty) = k.as_type() { - write!(w, "t"); - enc_ty(w, cx, ty); - } else if let Some(r) = k.as_region() { - write!(w, "r"); - enc_region(w, cx, r); - } else { - bug!() - } - } - write!(w, "]"); -} - -fn enc_region(w: &mut Cursor>, cx: &ctxt, r: &ty::Region) { - match *r { - ty::ReLateBound(id, br) => { - write!(w, "b[{}|", id.depth); - enc_bound_region(w, cx, br); - write!(w, "]"); - } - ty::ReEarlyBound(ref data) => { - write!(w, "B[{}|{}]", - data.index, - data.name); - } - ty::ReFree(ref fr) => { - write!(w, "f["); - enc_scope(w, cx, fr.scope); - write!(w, "|"); - enc_bound_region(w, cx, fr.bound_region); - write!(w, "]"); - } - ty::ReScope(scope) => { - write!(w, "s"); - enc_scope(w, cx, scope); - write!(w, "|"); - } - ty::ReStatic => { - write!(w, "t"); - } - ty::ReEmpty => { - write!(w, "e"); - } - ty::ReErased => { - write!(w, "E"); - } - ty::ReVar(_) | ty::ReSkolemized(..) => { - // these should not crop up after typeck - bug!("cannot encode region variables"); - } - } -} - -fn enc_scope(w: &mut Cursor>, cx: &ctxt, scope: region::CodeExtent) { - match cx.tcx.region_maps.code_extent_data(scope) { - region::CodeExtentData::CallSiteScope { - fn_id, body_id } => write!(w, "C[{}|{}]", fn_id, body_id), - region::CodeExtentData::ParameterScope { - fn_id, body_id } => write!(w, "P[{}|{}]", fn_id, body_id), - region::CodeExtentData::Misc(node_id) => write!(w, "M{}", node_id), - region::CodeExtentData::Remainder(region::BlockRemainder { - block: b, first_statement_index: i }) => write!(w, "B[{}|{}]", b, i), - region::CodeExtentData::DestructionScope(node_id) => write!(w, "D{}", node_id), - }; -} - -fn enc_bound_region(w: &mut Cursor>, cx: &ctxt, br: ty::BoundRegion) { - match br { - ty::BrAnon(idx) => { - write!(w, "a{}|", idx); - } - ty::BrNamed(d, name, issue32330) => { - write!(w, "[{}|{}|", - (cx.ds)(cx.tcx, d), - name); - - match issue32330 { - ty::Issue32330::WontChange => - write!(w, "n]"), - ty::Issue32330::WillChange { fn_def_id, region_name } => - write!(w, "y{}|{}]", (cx.ds)(cx.tcx, fn_def_id), region_name), - }; - } - ty::BrFresh(id) => { - write!(w, "f{}|", id); - } - ty::BrEnv => { - write!(w, "e|"); - } - } -} - -fn enc_trait_ref<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, - s: ty::TraitRef<'tcx>) { - write!(w, "{}|", (cx.ds)(cx.tcx, s.def_id)); - enc_substs(w, cx, s.substs); -} - -fn enc_existential_trait_ref<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, - s: ty::ExistentialTraitRef<'tcx>) { - write!(w, "{}|", (cx.ds)(cx.tcx, s.def_id)); - enc_substs(w, cx, s.substs); -} - -fn enc_unsafety(w: &mut Cursor>, p: hir::Unsafety) { - match p { - hir::Unsafety::Normal => write!(w, "n"), - hir::Unsafety::Unsafe => write!(w, "u"), - }; -} - -fn enc_abi(w: &mut Cursor>, abi: Abi) { - write!(w, "["); - write!(w, "{}", abi.name()); - write!(w, "]"); -} - -fn enc_bare_fn_ty<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, - ft: &ty::BareFnTy<'tcx>) { - enc_unsafety(w, ft.unsafety); - enc_abi(w, ft.abi); - enc_fn_sig(w, cx, &ft.sig); -} - -fn enc_fn_sig<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, - fsig: &ty::PolyFnSig<'tcx>) { - write!(w, "["); - for ty in &fsig.0.inputs { - enc_ty(w, cx, *ty); - } - write!(w, "]"); - if fsig.0.variadic { - write!(w, "V"); - } else { - write!(w, "N"); - } - enc_ty(w, cx, fsig.0.output); -} - -fn enc_builtin_bounds(w: &mut Cursor>, _cx: &ctxt, bs: &ty::BuiltinBounds) { - for bound in bs { - match bound { - ty::BoundSend => write!(w, "S"), - ty::BoundSized => write!(w, "Z"), - ty::BoundCopy => write!(w, "P"), - ty::BoundSync => write!(w, "T"), - }; - } - - write!(w, "."); -} - -fn enc_existential_projection<'a, 'tcx>(w: &mut Cursor>, - cx: &ctxt<'a, 'tcx>, - data: &ty::ExistentialProjection<'tcx>) { - enc_existential_trait_ref(w, cx, data.trait_ref); - write!(w, "{}|", data.item_name); - enc_ty(w, cx, data.ty); -} diff --git a/src/libserialize/collection_impls.rs b/src/libserialize/collection_impls.rs index 7b5092e8848e4..ba9bf2b86a60f 100644 --- a/src/libserialize/collection_impls.rs +++ b/src/libserialize/collection_impls.rs @@ -134,7 +134,7 @@ impl< fn encode(&self, s: &mut S) -> Result<(), S::Error> { let mut bits = 0; for item in self { - bits |= item.to_usize(); + bits |= 1 << item.to_usize(); } s.emit_usize(bits) } @@ -148,7 +148,7 @@ impl< let mut set = EnumSet::new(); for bit in 0..(mem::size_of::()*8) { if bits & (1 << bit) != 0 { - set.insert(CLike::from_usize(1 << bit)); + set.insert(CLike::from_usize(bit)); } } Ok(set) From 8734aaa33ed745a09b983bea9a89b6278b1b082c Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Mon, 19 Sep 2016 23:49:01 +0300 Subject: [PATCH 19/39] rustc_metadata: move more RBML tags to auto-serialization. --- src/librustc/dep_graph/dep_node.rs | 15 +- src/librustc/hir/def.rs | 2 +- src/librustc/hir/map/mod.rs | 22 +- src/librustc/middle/cstore.rs | 70 +- src/librustc/middle/dead.rs | 2 +- src/librustc/middle/lang_items.rs | 2 +- src/librustc/session/config.rs | 2 +- src/librustc/traits/select.rs | 2 +- .../traits/specialize/specialization_graph.rs | 63 +- src/librustc/ty/context.rs | 15 +- src/librustc/ty/maps.rs | 4 +- src/librustc/ty/mod.rs | 148 +-- src/librustc_const_eval/eval.rs | 14 +- src/librustc_metadata/common.rs | 124 ++- src/librustc_metadata/creader.rs | 14 +- src/librustc_metadata/csearch.rs | 114 +- src/librustc_metadata/cstore.rs | 22 +- src/librustc_metadata/decoder.rs | 999 ++++++------------ src/librustc_metadata/encoder.rs | 940 +++++++--------- src/librustc_metadata/index_builder.rs | 67 +- src/librustc_metadata/lib.rs | 1 + src/librustc_metadata/rbml/reader.rs | 132 +-- src/librustc_metadata/rbml/writer.rs | 47 +- src/librustc_resolve/build_reduced_graph.rs | 37 +- src/librustc_resolve/lib.rs | 1 + src/librustc_save_analysis/lib.rs | 6 +- src/librustc_trans/collector.rs | 24 +- src/librustc_trans/meth.rs | 2 +- src/librustc_trans/mir/constant.rs | 16 +- src/librustc_typeck/check/method/mod.rs | 29 +- src/librustc_typeck/check/method/probe.rs | 20 +- src/librustc_typeck/check/method/suggest.rs | 39 +- src/librustc_typeck/coherence/mod.rs | 6 +- src/librustc_typeck/coherence/overlap.rs | 6 +- src/librustc_typeck/collect.rs | 31 +- src/librustdoc/clean/inline.rs | 110 +- src/librustdoc/clean/mod.rs | 10 +- src/librustdoc/core.rs | 8 +- src/librustdoc/test.rs | 2 +- src/librustdoc/visit_lib.rs | 41 +- 40 files changed, 1077 insertions(+), 2132 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 18179027c25de..3cf7548e3209a 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -103,18 +103,13 @@ pub enum DepNode { // table in the tcx (or elsewhere) maps to one of these // nodes. Often we map multiple tables to the same node if there // is no point in distinguishing them (e.g., both the type and - // predicates for an item wind up in `ItemSignature`). Other - // times, such as `ImplItems` vs `TraitItemDefIds`, tables which - // might be mergable are kept distinct because the sets of def-ids - // to which they apply are disjoint, and hence we might as well - // have distinct labels for easier debugging. + // predicates for an item wind up in `ItemSignature`). ImplOrTraitItems(D), ItemSignature(D), FieldTy(D), SizedConstraint(D), - TraitItemDefIds(D), + ImplOrTraitItemIds(D), InherentImpls(D), - ImplItems(D), // The set of impls for a given trait. Ultimately, it would be // nice to get more fine-grained here (e.g., to include a @@ -162,9 +157,8 @@ impl DepNode { ImplOrTraitItems, ItemSignature, FieldTy, - TraitItemDefIds, + ImplOrTraitItemIds, InherentImpls, - ImplItems, TraitImpls, ReprHints, } @@ -231,9 +225,8 @@ impl DepNode { ItemSignature(ref d) => op(d).map(ItemSignature), FieldTy(ref d) => op(d).map(FieldTy), SizedConstraint(ref d) => op(d).map(SizedConstraint), - TraitItemDefIds(ref d) => op(d).map(TraitItemDefIds), + ImplOrTraitItemIds(ref d) => op(d).map(ImplOrTraitItemIds), InherentImpls(ref d) => op(d).map(InherentImpls), - ImplItems(ref d) => op(d).map(ImplItems), TraitImpls(ref d) => op(d).map(TraitImpls), TraitItems(ref d) => op(d).map(TraitItems), ReprHints(ref d) => op(d).map(ReprHints), diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs index b4418ed424ea3..fddf09c990566 100644 --- a/src/librustc/hir/def.rs +++ b/src/librustc/hir/def.rs @@ -92,7 +92,7 @@ pub type DefMap = NodeMap; // within. pub type ExportMap = NodeMap>; -#[derive(Copy, Clone)] +#[derive(Copy, Clone, RustcEncodable, RustcDecodable)] pub struct Export { pub name: ast::Name, // The name of the target. pub def_id: DefId, // The definition of the target. diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index b728f1cbca097..b351bd427acbc 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -580,22 +580,24 @@ impl<'ast> Map<'ast> { } } - pub fn expect_struct(&self, id: NodeId) -> &'ast VariantData { + pub fn expect_variant_data(&self, id: NodeId) -> &'ast VariantData { match self.find(id) { Some(NodeItem(i)) => { match i.node { - ItemStruct(ref struct_def, _) => struct_def, - _ => bug!("struct ID bound to non-struct") + ItemStruct(ref struct_def, _) | + ItemUnion(ref struct_def, _) => struct_def, + _ => { + bug!("struct ID bound to non-struct {}", + self.node_to_string(id)); + } } } - Some(NodeVariant(variant)) => { - if variant.node.data.is_struct() { - &variant.node.data - } else { - bug!("struct ID bound to enum variant that isn't struct-like") - } + Some(NodeStructCtor(data)) => data, + Some(NodeVariant(variant)) => &variant.node.data, + _ => { + bug!("expected struct or variant, found {}", + self.node_to_string(id)); } - _ => bug!("expected struct, found {}", self.node_to_string(id)), } } diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 1d6047579f6cf..52cadd76c64cb 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -28,14 +28,13 @@ use hir::map as hir_map; use hir::map::definitions::DefKey; use hir::svh::Svh; use middle::lang_items; -use ty::{self, Ty, TyCtxt, VariantKind}; +use ty::{self, Ty, TyCtxt}; use mir::repr::Mir; use mir::mir_map::MirMap; use session::Session; use session::config::PanicStrategy; use session::search_paths::PathKind; -use util::nodemap::{FnvHashMap, NodeSet, DefIdMap}; -use std::rc::Rc; +use util::nodemap::{NodeSet, DefIdMap}; use std::path::PathBuf; use syntax::ast; use syntax::attr; @@ -47,7 +46,6 @@ use rustc_back::target::Target; use hir; use hir::intravisit::Visitor; -pub use self::DefLike::{DlDef, DlField, DlImpl}; pub use self::NativeLibraryKind::{NativeStatic, NativeFramework, NativeUnknown}; // lonely orphan structs and enums looking for a better home @@ -67,27 +65,17 @@ pub struct CrateSource { pub cnum: CrateNum, } -#[derive(Copy, Debug, PartialEq, Clone)] +#[derive(Copy, Debug, PartialEq, Clone, RustcEncodable, RustcDecodable)] pub enum LinkagePreference { RequireDynamic, RequireStatic, } -enum_from_u32! { - #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] - pub enum NativeLibraryKind { - NativeStatic, // native static library (.a archive) - NativeFramework, // OSX-specific - NativeUnknown, // default way to specify a dynamic library - } -} - -// Something that a name can resolve to. -#[derive(Copy, Clone, Debug)] -pub enum DefLike { - DlDef(Def), - DlImpl(DefId), - DlField +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] +pub enum NativeLibraryKind { + NativeStatic, // native static library (.a archive) + NativeFramework, // OSX-specific + NativeUnknown, // default way to specify a dynamic library } /// The data we save and restore about an inlined item or method. This is not @@ -110,7 +98,7 @@ pub enum InlinedItemRef<'a> { #[derive(Copy, Clone)] pub struct ChildItem { - pub def: DefLike, + pub def: Def, pub name: ast::Name, pub vis: ty::Visibility, } @@ -166,21 +154,15 @@ pub trait CrateStore<'tcx> { fn inherent_implementations_for_type(&self, def_id: DefId) -> Vec; // trait info - fn implementations_of_trait(&self, def_id: DefId) -> Vec; - fn provided_trait_methods<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) - -> Vec>>; - fn trait_item_def_ids(&self, def: DefId) - -> Vec; + fn implementations_of_trait(&self, filter: Option) -> Vec; // impl info - fn impl_items(&self, impl_def_id: DefId) -> Vec; + fn impl_or_trait_items(&self, def_id: DefId) -> Vec; fn impl_trait_ref<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> Option>; - fn impl_polarity(&self, def: DefId) -> Option; + fn impl_polarity(&self, def: DefId) -> hir::ImplPolarity; fn custom_coerce_unsized_kind(&self, def: DefId) -> Option; - fn associated_consts<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) - -> Vec>>; fn impl_parent(&self, impl_def_id: DefId) -> Option; // trait/impl-item info @@ -191,12 +173,10 @@ pub trait CrateStore<'tcx> { // flags fn is_const_fn(&self, did: DefId) -> bool; fn is_defaulted_trait(&self, did: DefId) -> bool; - fn is_impl(&self, did: DefId) -> bool; fn is_default_impl(&self, impl_did: DefId) -> bool; fn is_extern_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, did: DefId) -> bool; fn is_foreign_item(&self, did: DefId) -> bool; fn is_statically_included_foreign_item(&self, id: ast::NodeId) -> bool; - fn is_typedef(&self, did: DefId) -> bool; // crate metadata fn dylib_dependency_formats(&self, cnum: CrateNum) @@ -218,8 +198,6 @@ pub trait CrateStore<'tcx> { fn original_crate_name(&self, cnum: CrateNum) -> InternedString; fn crate_hash(&self, cnum: CrateNum) -> Svh; fn crate_disambiguator(&self, cnum: CrateNum) -> InternedString; - fn crate_struct_field_attrs(&self, cnum: CrateNum) - -> FnvHashMap>; fn plugin_registrar_fn(&self, cnum: CrateNum) -> Option; fn native_libraries(&self, cnum: CrateNum) -> Vec<(NativeLibraryKind, String)>; fn reachable_ids(&self, cnum: CrateNum) -> Vec; @@ -232,12 +210,10 @@ pub trait CrateStore<'tcx> { -> Option; fn def_key(&self, def: DefId) -> hir_map::DefKey; fn relative_def_path(&self, def: DefId) -> Option; - fn variant_kind(&self, def_id: DefId) -> Option; fn struct_ctor_def_id(&self, struct_def_id: DefId) -> Option; fn tuple_struct_definition_if_ctor(&self, did: DefId) -> Option; fn struct_field_names(&self, def: DefId) -> Vec; fn item_children(&self, did: DefId) -> Vec; - fn crate_top_level_items(&self, cnum: CrateNum) -> Vec; // misc. metadata fn maybe_get_item_ast<'a>(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) @@ -344,11 +320,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { fn inherent_implementations_for_type(&self, def_id: DefId) -> Vec { vec![] } // trait info - fn implementations_of_trait(&self, def_id: DefId) -> Vec { vec![] } - fn provided_trait_methods<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) - -> Vec>> { bug!("provided_trait_methods") } - fn trait_item_def_ids(&self, def: DefId) - -> Vec { bug!("trait_item_def_ids") } + fn implementations_of_trait(&self, filter: Option) -> Vec { vec![] } fn def_index_for_def_key(&self, cnum: CrateNum, def: DefKey) @@ -357,16 +329,14 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { } // impl info - fn impl_items(&self, impl_def_id: DefId) -> Vec - { bug!("impl_items") } + fn impl_or_trait_items(&self, def_id: DefId) -> Vec + { bug!("impl_or_trait_items") } fn impl_trait_ref<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> Option> { bug!("impl_trait_ref") } - fn impl_polarity(&self, def: DefId) -> Option { bug!("impl_polarity") } + fn impl_polarity(&self, def: DefId) -> hir::ImplPolarity { bug!("impl_polarity") } fn custom_coerce_unsized_kind(&self, def: DefId) -> Option { bug!("custom_coerce_unsized_kind") } - fn associated_consts<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) - -> Vec>> { bug!("associated_consts") } fn impl_parent(&self, def: DefId) -> Option { bug!("impl_parent") } // trait/impl-item info @@ -377,13 +347,11 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { // flags fn is_const_fn(&self, did: DefId) -> bool { bug!("is_const_fn") } fn is_defaulted_trait(&self, did: DefId) -> bool { bug!("is_defaulted_trait") } - fn is_impl(&self, did: DefId) -> bool { bug!("is_impl") } fn is_default_impl(&self, impl_did: DefId) -> bool { bug!("is_default_impl") } fn is_extern_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, did: DefId) -> bool { bug!("is_extern_item") } fn is_foreign_item(&self, did: DefId) -> bool { bug!("is_foreign_item") } fn is_statically_included_foreign_item(&self, id: ast::NodeId) -> bool { false } - fn is_typedef(&self, did: DefId) -> bool { bug!("is_typedef") } // crate metadata fn dylib_dependency_formats(&self, cnum: CrateNum) @@ -411,9 +379,6 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { fn crate_hash(&self, cnum: CrateNum) -> Svh { bug!("crate_hash") } fn crate_disambiguator(&self, cnum: CrateNum) -> InternedString { bug!("crate_disambiguator") } - fn crate_struct_field_attrs(&self, cnum: CrateNum) - -> FnvHashMap> - { bug!("crate_struct_field_attrs") } fn plugin_registrar_fn(&self, cnum: CrateNum) -> Option { bug!("plugin_registrar_fn") } fn native_libraries(&self, cnum: CrateNum) -> Vec<(NativeLibraryKind, String)> @@ -426,15 +391,12 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { fn relative_def_path(&self, def: DefId) -> Option { bug!("relative_def_path") } - fn variant_kind(&self, def_id: DefId) -> Option { bug!("variant_kind") } fn struct_ctor_def_id(&self, struct_def_id: DefId) -> Option { bug!("struct_ctor_def_id") } fn tuple_struct_definition_if_ctor(&self, did: DefId) -> Option { bug!("tuple_struct_definition_if_ctor") } fn struct_field_names(&self, def: DefId) -> Vec { bug!("struct_field_names") } fn item_children(&self, did: DefId) -> Vec { bug!("item_children") } - fn crate_top_level_items(&self, cnum: CrateNum) -> Vec - { bug!("crate_top_level_items") } // misc. metadata fn maybe_get_item_ast<'a>(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 9db6ac1dcefd0..2c952e9f86349 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -470,7 +470,7 @@ impl<'a, 'tcx> DeadVisitor<'a, 'tcx> { // This is done to handle the case where, for example, the static // method of a private type is used, but the type itself is never // called directly. - let impl_items = self.tcx.impl_items.borrow(); + let impl_items = self.tcx.impl_or_trait_item_ids.borrow(); if let Some(impl_list) = self.tcx.inherent_impls.borrow().get(&self.tcx.map.local_def_id(id)) { for impl_did in impl_list.iter() { diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index d1769d5cbc51b..078cce9c49ff4 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -43,7 +43,7 @@ macro_rules! language_item_table { enum_from_u32! { - #[derive(Copy, Clone, PartialEq, Eq, Hash)] + #[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub enum LangItem { $($variant,)* } diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 2009e18f6ee20..8dd5d4d45f7a4 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -493,7 +493,7 @@ impl Passes { } } -#[derive(Clone, PartialEq, Hash)] +#[derive(Clone, PartialEq, Hash, RustcEncodable, RustcDecodable)] pub enum PanicStrategy { Unwind, Abort, diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 94dba7d12a8c7..9d7131dc96cc5 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -814,7 +814,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { fn filter_negative_impls(&self, candidate: SelectionCandidate<'tcx>) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> { if let ImplCandidate(def_id) = candidate { - if self.tcx().trait_impl_polarity(def_id) == Some(hir::ImplPolarity::Negative) { + if self.tcx().trait_impl_polarity(def_id) == hir::ImplPolarity::Negative { return Err(Unimplemented) } } diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs index 13193e1b2d71b..4339b1a254f20 100644 --- a/src/librustc/traits/specialize/specialization_graph.rs +++ b/src/librustc/traits/specialize/specialization_graph.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::cell; use std::rc::Rc; use super::{OverlapError, specializes}; @@ -287,21 +286,10 @@ impl<'a, 'gcx, 'tcx> Node { /// Iterate over the items defined directly by the given (impl or trait) node. pub fn items(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> NodeItems<'a, 'gcx> { - match *self { - Node::Impl(impl_def_id) => { - NodeItems::Impl { - tcx: tcx.global_tcx(), - items: cell::Ref::map(tcx.impl_items.borrow(), - |impl_items| &impl_items[&impl_def_id]), - idx: 0, - } - } - Node::Trait(trait_def_id) => { - NodeItems::Trait { - items: tcx.trait_items(trait_def_id).clone(), - idx: 0, - } - } + NodeItems { + tcx: tcx.global_tcx(), + items: tcx.impl_or_trait_items(self.def_id()), + idx: 0, } } @@ -314,42 +302,23 @@ impl<'a, 'gcx, 'tcx> Node { } /// An iterator over the items defined within a trait or impl. -pub enum NodeItems<'a, 'tcx: 'a> { - Impl { - tcx: TyCtxt<'a, 'tcx, 'tcx>, - items: cell::Ref<'a, Vec>, - idx: usize, - }, - Trait { - items: Rc>>, - idx: usize, - }, +pub struct NodeItems<'a, 'tcx: 'a> { + tcx: TyCtxt<'a, 'tcx, 'tcx>, + items: Rc>, + idx: usize } impl<'a, 'tcx> Iterator for NodeItems<'a, 'tcx> { type Item = ImplOrTraitItem<'tcx>; fn next(&mut self) -> Option> { - match *self { - NodeItems::Impl { tcx, ref items, ref mut idx } => { - let items_table = tcx.impl_or_trait_items.borrow(); - if *idx < items.len() { - let item_def_id = items[*idx].def_id(); - let item = items_table[&item_def_id].clone(); - *idx += 1; - Some(item) - } else { - None - } - } - NodeItems::Trait { ref items, ref mut idx } => { - if *idx < items.len() { - let item = items[*idx].clone(); - *idx += 1; - Some(item) - } else { - None - } - } + if self.idx < self.items.len() { + let item_def_id = self.items[self.idx].def_id(); + let items_table = self.tcx.impl_or_trait_items.borrow(); + let item = items_table[&item_def_id].clone(); + self.idx += 1; + Some(item) + } else { + None } } } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 338ea6b0dd6d4..0d6beb34c6902 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -330,8 +330,8 @@ pub struct GlobalCtxt<'tcx> { /// Maps from a trait item to the trait item "descriptor" pub impl_or_trait_items: RefCell>>, - /// Maps from a trait def-id to a list of the def-ids of its trait items - pub trait_item_def_ids: RefCell>>, + /// Maps from an impl/trait def-id to a list of the def-ids of its items + pub impl_or_trait_item_ids: RefCell>>, /// A cache for the trait_items() routine; note that the routine /// itself pushes the `TraitItems` dependency node. @@ -392,12 +392,6 @@ pub struct GlobalCtxt<'tcx> { /// Methods in these implementations don't need to be exported. pub inherent_impls: RefCell>>, - /// Maps a DefId of an impl to a list of its items. - /// Note that this contains all of the impls that we know about, - /// including ones in other crates. It's not clear that this is the best - /// way to do it. - pub impl_items: RefCell>>, - /// Set of used unsafe nodes (functions or blocks). Unsafe nodes not /// present in this set can be warned about. pub used_unsafe: RefCell, @@ -734,13 +728,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { rcache: RefCell::new(FnvHashMap()), tc_cache: RefCell::new(FnvHashMap()), impl_or_trait_items: RefCell::new(DepTrackingMap::new(dep_graph.clone())), - trait_item_def_ids: RefCell::new(DepTrackingMap::new(dep_graph.clone())), + impl_or_trait_item_ids: RefCell::new(DepTrackingMap::new(dep_graph.clone())), trait_items_cache: RefCell::new(DepTrackingMap::new(dep_graph.clone())), ty_param_defs: RefCell::new(NodeMap()), normalized_cache: RefCell::new(FnvHashMap()), lang_items: lang_items, inherent_impls: RefCell::new(DepTrackingMap::new(dep_graph.clone())), - impl_items: RefCell::new(DepTrackingMap::new(dep_graph.clone())), used_unsafe: RefCell::new(NodeSet()), used_mut_nodes: RefCell::new(NodeSet()), used_trait_imports: RefCell::new(NodeSet()), @@ -1401,7 +1394,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn trait_items(self, trait_did: DefId) -> Rc>> { self.trait_items_cache.memoize(trait_did, || { - let def_ids = self.trait_item_def_ids(trait_did); + let def_ids = self.impl_or_trait_items(trait_did); Rc::new(def_ids.iter() .map(|d| self.impl_or_trait_item(d.def_id())) .collect()) diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index 5772d16c6d43d..5e029cf98dc62 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -34,13 +34,13 @@ dep_map_ty! { Tcache: ItemSignature(DefId) -> Ty<'tcx> } dep_map_ty! { Generics: ItemSignature(DefId) -> &'tcx ty::Generics<'tcx> } dep_map_ty! { Predicates: ItemSignature(DefId) -> ty::GenericPredicates<'tcx> } dep_map_ty! { SuperPredicates: ItemSignature(DefId) -> ty::GenericPredicates<'tcx> } -dep_map_ty! { TraitItemDefIds: TraitItemDefIds(DefId) -> Rc> } +dep_map_ty! { ImplOrTraitItemIds: ImplOrTraitItemIds(DefId) + -> Rc> } dep_map_ty! { ImplTraitRefs: ItemSignature(DefId) -> Option> } dep_map_ty! { TraitDefs: ItemSignature(DefId) -> &'tcx ty::TraitDef<'tcx> } dep_map_ty! { AdtDefs: ItemSignature(DefId) -> ty::AdtDefMaster<'tcx> } dep_map_ty! { ItemVariances: ItemSignature(DefId) -> Rc> } dep_map_ty! { InherentImpls: InherentImpls(DefId) -> Vec } -dep_map_ty! { ImplItems: ImplItems(DefId) -> Vec } dep_map_ty! { TraitItems: TraitItems(DefId) -> Rc>> } dep_map_ty! { ReprHints: ReprHints(DefId) -> Rc> } dep_map_ty! { InlinedClosures: Hir(DefId) -> ast::NodeId } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 59475b4222635..3eb9f8593e3af 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -50,7 +50,6 @@ use syntax_pos::{DUMMY_SP, Span}; use rustc_const_math::ConstInt; use hir; -use hir::{ItemImpl, ItemTrait, PatKind}; use hir::intravisit::Visitor; pub use self::sty::{Binder, DebruijnIndex}; @@ -251,7 +250,7 @@ impl<'tcx> ImplOrTraitItem<'tcx> { } } -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Copy, Debug, RustcEncodable, RustcDecodable)] pub enum ImplOrTraitItemId { ConstTraitItemId(DefId), MethodTraitItemId(DefId), @@ -268,7 +267,7 @@ impl ImplOrTraitItemId { } } -#[derive(Clone, Debug, PartialEq, Eq, Copy)] +#[derive(Clone, Debug, PartialEq, Eq, Copy, RustcEncodable, RustcDecodable)] pub enum Visibility { /// Visible everywhere (including in other crates). Public, @@ -346,34 +345,12 @@ pub struct Method<'tcx> { pub explicit_self: ExplicitSelfCategory<'tcx>, pub vis: Visibility, pub defaultness: hir::Defaultness, + pub has_body: bool, pub def_id: DefId, pub container: ImplOrTraitItemContainer, } impl<'tcx> Method<'tcx> { - pub fn new(name: Name, - generics: &'tcx ty::Generics<'tcx>, - predicates: GenericPredicates<'tcx>, - fty: &'tcx BareFnTy<'tcx>, - explicit_self: ExplicitSelfCategory<'tcx>, - vis: Visibility, - defaultness: hir::Defaultness, - def_id: DefId, - container: ImplOrTraitItemContainer) - -> Method<'tcx> { - Method { - name: name, - generics: generics, - predicates: predicates, - fty: fty, - explicit_self: explicit_self, - vis: vis, - defaultness: defaultness, - def_id: def_id, - container: container, - } - } - pub fn container_id(&self) -> DefId { match self.container { TraitContainer(id) => id, @@ -2236,7 +2213,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { match self.map.find(id) { Some(ast_map::NodeLocal(pat)) => { match pat.node { - PatKind::Binding(_, ref path1, _) => path1.node.as_str(), + hir::PatKind::Binding(_, ref path1, _) => path1.node.as_str(), _ => { bug!("Variable id {} maps to {:?}, not local", id, pat); }, @@ -2299,84 +2276,19 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } pub fn provided_trait_methods(self, id: DefId) -> Vec>> { - if let Some(id) = self.map.as_local_node_id(id) { - if let ItemTrait(.., ref ms) = self.map.expect_item(id).node { - ms.iter().filter_map(|ti| { - if let hir::MethodTraitItem(_, Some(_)) = ti.node { - match self.impl_or_trait_item(self.map.local_def_id(ti.id)) { - MethodTraitItem(m) => Some(m), - _ => { - bug!("provided_trait_methods(): \ - non-method item found from \ - looking up provided method?!") - } - } - } else { - None - } - }).collect() - } else { - bug!("provided_trait_methods: `{:?}` is not a trait", id) + self.impl_or_trait_items(id).iter().filter_map(|id| { + match self.impl_or_trait_item(id.def_id()) { + MethodTraitItem(ref m) if m.has_body => Some(m.clone()), + _ => None } - } else { - self.sess.cstore.provided_trait_methods(self.global_tcx(), id) - } + }).collect() } - pub fn associated_consts(self, id: DefId) -> Vec>> { + pub fn trait_impl_polarity(self, id: DefId) -> hir::ImplPolarity { if let Some(id) = self.map.as_local_node_id(id) { match self.map.expect_item(id).node { - ItemTrait(.., ref tis) => { - tis.iter().filter_map(|ti| { - if let hir::ConstTraitItem(..) = ti.node { - match self.impl_or_trait_item(self.map.local_def_id(ti.id)) { - ConstTraitItem(ac) => Some(ac), - _ => { - bug!("associated_consts(): \ - non-const item found from \ - looking up a constant?!") - } - } - } else { - None - } - }).collect() - } - ItemImpl(.., ref iis) => { - iis.iter().filter_map(|ii| { - if let hir::ImplItemKind::Const(..) = ii.node { - match self.impl_or_trait_item(self.map.local_def_id(ii.id)) { - ConstTraitItem(ac) => Some(ac), - _ => { - bug!("associated_consts(): \ - non-const item found from \ - looking up a constant?!") - } - } - } else { - None - } - }).collect() - } - _ => { - bug!("associated_consts: `{:?}` is not a trait or impl", id) - } - } - } else { - self.sess.cstore.associated_consts(self.global_tcx(), id) - } - } - - pub fn trait_impl_polarity(self, id: DefId) -> Option { - if let Some(id) = self.map.as_local_node_id(id) { - match self.map.find(id) { - Some(ast_map::NodeItem(item)) => { - match item.node { - hir::ItemImpl(_, polarity, ..) => Some(polarity), - _ => None - } - } - _ => None + hir::ItemImpl(_, polarity, ..) => polarity, + ref item => bug!("trait_impl_polarity: {:?} not an impl", item) } } else { self.sess.cstore.impl_polarity(id) @@ -2409,10 +2321,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { .expect("missing ImplOrTraitItem in metadata")) } - pub fn trait_item_def_ids(self, id: DefId) -> Rc> { + pub fn impl_or_trait_items(self, id: DefId) -> Rc> { lookup_locally_or_in_crate_store( - "trait_item_def_ids", id, &self.trait_item_def_ids, - || Rc::new(self.sess.cstore.trait_item_def_ids(id))) + "impl_or_trait_items", id, &self.impl_or_trait_item_ids, + || Rc::new(self.sess.cstore.impl_or_trait_items(id))) } /// Returns the trait-ref corresponding to a given impl, or None if it is @@ -2423,20 +2335,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { || self.sess.cstore.impl_trait_ref(self.global_tcx(), id)) } - /// Returns whether this DefId refers to an impl - pub fn is_impl(self, id: DefId) -> bool { - if let Some(id) = self.map.as_local_node_id(id) { - if let Some(ast_map::NodeItem( - &hir::Item { node: hir::ItemImpl(..), .. })) = self.map.find(id) { - true - } else { - false - } - } else { - self.sess.cstore.is_impl(id) - } - } - /// Returns a path resolution for node id if it exists, panics otherwise. pub fn expect_resolution(self, id: NodeId) -> PathResolution { *self.def_map.borrow().get(&id).expect("no def-map entry for node id") @@ -2699,10 +2597,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { debug!("populate_implementations_for_primitive_if_necessary: searching for {:?}", primitive_def_id); - let impl_items = self.sess.cstore.impl_items(primitive_def_id); + let impl_items = self.sess.cstore.impl_or_trait_items(primitive_def_id); // Store the implementation info. - self.impl_items.borrow_mut().insert(primitive_def_id, impl_items); + self.impl_or_trait_item_ids.borrow_mut().insert(primitive_def_id, Rc::new(impl_items)); self.populated_external_primitive_impls.borrow_mut().insert(primitive_def_id); } @@ -2728,8 +2626,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let inherent_impls = self.sess.cstore.inherent_implementations_for_type(type_id); for &impl_def_id in &inherent_impls { // Store the implementation info. - let impl_items = self.sess.cstore.impl_items(impl_def_id); - self.impl_items.borrow_mut().insert(impl_def_id, impl_items); + let impl_items = self.sess.cstore.impl_or_trait_items(impl_def_id); + self.impl_or_trait_item_ids.borrow_mut().insert(impl_def_id, Rc::new(impl_items)); } self.inherent_impls.borrow_mut().insert(type_id, inherent_impls); @@ -2758,8 +2656,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.record_trait_has_default_impl(trait_id); } - for impl_def_id in self.sess.cstore.implementations_of_trait(trait_id) { - let impl_items = self.sess.cstore.impl_items(impl_def_id); + for impl_def_id in self.sess.cstore.implementations_of_trait(Some(trait_id)) { + let impl_items = self.sess.cstore.impl_or_trait_items(impl_def_id); let trait_ref = self.impl_trait_ref(impl_def_id).unwrap(); // Record the trait->implementation mapping. @@ -2779,7 +2677,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } // Store the implementation info. - self.impl_items.borrow_mut().insert(impl_def_id, impl_items); + self.impl_or_trait_item_ids.borrow_mut().insert(impl_def_id, Rc::new(impl_items)); } def.flags.set(def.flags.get() | TraitFlags::IMPLS_VALID); @@ -3012,7 +2910,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } /// The category of explicit self. -#[derive(Clone, Copy, Eq, PartialEq, Debug)] +#[derive(Clone, Copy, Eq, PartialEq, Debug, RustcEncodable, RustcDecodable)] pub enum ExplicitSelfCategory<'tcx> { Static, ByValue, diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index ede13aa4dc8b2..fe3c498d184be 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -1080,9 +1080,17 @@ fn resolve_trait_associated_const<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // when constructing the inference context above. match selection { traits::VtableImpl(ref impl_data) => { - match tcx.associated_consts(impl_data.impl_def_id) - .iter().find(|ic| ic.name == ti.name) { - Some(ic) => lookup_const_by_id(tcx, ic.def_id, None), + let ac = tcx.impl_or_trait_items(impl_data.impl_def_id) + .iter().filter_map(|id| { + match *id { + ty::ConstTraitItemId(def_id) => { + Some(tcx.impl_or_trait_item(def_id)) + } + _ => None + } + }).find(|ic| ic.name() == ti.name); + match ac { + Some(ic) => lookup_const_by_id(tcx, ic.def_id(), None), None => match ti.node { hir::ConstTraitItem(ref ty, Some(ref expr)) => { Some((&*expr, tcx.ast_ty_to_prim_ty(ty))) diff --git a/src/librustc_metadata/common.rs b/src/librustc_metadata/common.rs index 123ed11a7a513..94581a3fc8976 100644 --- a/src/librustc_metadata/common.rs +++ b/src/librustc_metadata/common.rs @@ -10,13 +10,38 @@ #![allow(non_camel_case_types, non_upper_case_globals)] +use rustc::ty; + +#[derive(Clone, Copy, Debug, PartialEq, RustcEncodable, RustcDecodable)] +pub enum Family { + ImmStatic, + MutStatic, + Fn, + Method, + AssociatedType, + Type, + Mod, + ForeignMod, + Enum, + Variant(ty::VariantKind), + Impl, + DefaultImpl, + Trait, + Struct(ty::VariantKind), + Union, + PublicField, + InheritedField, + Const, + AssociatedConst, +} + // GAP 0x00...0x19 pub const tag_items: usize = 0x100; // top-level only pub const tag_paths_data_name: usize = 0x20; -pub const tag_def_id: usize = 0x21; +pub const tag_def_index: usize = 0x21; pub const tag_items_data: usize = 0x22; @@ -26,9 +51,7 @@ pub const tag_items_data_item_family: usize = 0x24; pub const tag_items_data_item_type: usize = 0x25; -// GAP 0x26 - -pub const tag_items_data_item_variant: usize = 0x27; +// GAP 0x26, 0x27 pub const tag_items_data_parent_item: usize = 0x28; @@ -47,19 +70,11 @@ pub const tag_attributes: usize = 0x101; // top-level only // The list of crates that this crate depends on pub const tag_crate_deps: usize = 0x102; // top-level only - -// A single crate dependency -pub const tag_crate_dep: usize = 0x35; - pub const tag_crate_hash: usize = 0x103; // top-level only pub const tag_crate_crate_name: usize = 0x104; // top-level only pub const tag_crate_disambiguator: usize = 0x113; // top-level only -pub const tag_crate_dep_crate_name: usize = 0x36; -pub const tag_crate_dep_hash: usize = 0x37; -pub const tag_crate_dep_explicitly_linked: usize = 0x38; // top-level only - -pub const tag_item_trait_item: usize = 0x3a; +// GAP 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a pub const tag_item_trait_ref: usize = 0x3b; @@ -68,26 +83,13 @@ pub const tag_disr_val: usize = 0x3c; // GAP 0x3d, 0x3e, 0x3f, 0x40 -pub const tag_item_field: usize = 0x41; +pub const tag_item_fields: usize = 0x41; // GAP 0x42 pub const tag_item_variances: usize = 0x43; -/* - trait items contain tag_item_trait_item elements, - impl items contain tag_item_impl_item elements, and classes - have both. That's because some code treats classes like traits, - and other code treats them like impls. Because classes can contain - both, tag_item_trait_item and tag_item_impl_item have to be two - different tags. - */ -pub const tag_item_impl_item: usize = 0x44; +// GAP 0x44 pub const tag_item_trait_method_explicit_self: usize = 0x45; - -// Reexports are found within module tags. Each reexport contains def_ids -// and names. -pub const tag_items_data_item_reexport: usize = 0x46; -pub const tag_items_data_item_reexport_def_id: usize = 0x47; -pub const tag_items_data_item_reexport_name: usize = 0x48; +// GAP 0x46, 0x47, 0x48 // used to encode crate_ctxt side tables pub const tag_ast: usize = 0x50; @@ -98,58 +100,58 @@ pub const tag_mir: usize = 0x52; // GAP 0x53...0x6a -pub const tag_item_trait_item_sort: usize = 0x70; +pub const tag_item_trait_item_has_body: usize = 0x70; pub const tag_crate_triple: usize = 0x105; // top-level only pub const tag_dylib_dependency_formats: usize = 0x106; // top-level only -// Language items are a top-level directory (for speed). Hierarchy: -// -// tag_lang_items -// - tag_lang_items_item -// - tag_lang_items_item_id: u32 -// - tag_lang_items_item_index: u32 - pub const tag_lang_items: usize = 0x107; // top-level only -pub const tag_lang_items_item: usize = 0x73; -pub const tag_lang_items_item_id: usize = 0x74; -pub const tag_lang_items_item_index: usize = 0x75; -pub const tag_lang_items_missing: usize = 0x76; -pub const tag_item_unnamed_field: usize = 0x77; +// GAP 0x73, 0x74, 0x75 + +pub const tag_lang_items_missing: usize = 0x76; // top-level only + +// GAP 0x77 + pub const tag_items_data_item_visibility: usize = 0x78; -pub const tag_items_data_item_inherent_impl: usize = 0x79; +pub const tag_items_data_item_inherent_impls: usize = 0x79; + // GAP 0x7a -pub const tag_mod_child: usize = 0x7b; + +// GAP 0x7c +pub const tag_mod_children: usize = 0x7b; + +// GAP 0x108 // top-level only + // GAP 0x7c // GAP 0x108 pub const tag_impls: usize = 0x109; // top-level only -pub const tag_impls_trait: usize = 0x7d; -pub const tag_impls_trait_impl: usize = 0x7e; -// GAP 0x7f, 0x80, 0x81 +// GAP 0x7d, 0x7e, 0x7f, 0x80, 0x81 pub const tag_native_libraries: usize = 0x10a; // top-level only -pub const tag_native_libraries_lib: usize = 0x82; -pub const tag_native_libraries_name: usize = 0x83; -pub const tag_native_libraries_kind: usize = 0x84; + +// GAP 0x82, 0x83, 0x84 pub const tag_plugin_registrar_fn: usize = 0x10b; // top-level only pub const tag_method_argument_names: usize = 0x85; -pub const tag_method_argument_name: usize = 0x86; + +// GAP 0x86 pub const tag_reachable_ids: usize = 0x10c; // top-level only -pub const tag_reachable_id: usize = 0x87; + +// GAP 0x87 pub const tag_items_data_item_stability: usize = 0x88; pub const tag_items_data_item_repr: usize = 0x89; -pub const tag_struct_fields: usize = 0x10d; // top-level only -pub const tag_struct_field: usize = 0x8a; +// GAP 0x10d // top-level only + +// GAP 0x8a pub const tag_items_data_item_struct_ctor: usize = 0x8b; pub const tag_attribute_is_sugared_doc: usize = 0x8c; @@ -160,10 +162,7 @@ pub const tag_item_generics: usize = 0x8f; // GAP 0x90, 0x91, 0x92, 0x93, 0x94 pub const tag_item_predicates: usize = 0x95; -// GAP 0x96 - -pub const tag_predicate: usize = 0x97; -// GAP 0x98, 0x99 +// GAP 0x96, 0x97, 0x98, 0x99 pub const tag_unsafety: usize = 0x9a; @@ -173,15 +172,14 @@ pub const tag_associated_type_name: usize = 0x9c; pub const tag_polarity: usize = 0x9d; pub const tag_macro_defs: usize = 0x10e; // top-level only -pub const tag_macro_def: usize = 0x9e; -pub const tag_macro_def_body: usize = 0x9f; -pub const tag_macro_def_span_lo: usize = 0xa8; -pub const tag_macro_def_span_hi: usize = 0xa9; + +// GAP 0x9e, 0x9f pub const tag_paren_sugar: usize = 0xa0; pub const tag_codemap: usize = 0xa1; -pub const tag_codemap_filemap: usize = 0xa2; + +// GAP 0xa2 pub const tag_item_super_predicates: usize = 0xa3; diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 2774ffdf6c772..7b6ed4e6b7648 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -264,7 +264,7 @@ impl<'a> CrateReader<'a> { // Check for (potential) conflicts with the local crate if self.local_crate_name == crate_name && - self.sess.local_crate_disambiguator() == disambiguator { + self.sess.local_crate_disambiguator() == &disambiguator[..] { span_fatal!(self.sess, span, E0519, "the current crate is indistinguishable from one of its \ dependencies: it has the same crate-name `{}` and was \ @@ -320,7 +320,6 @@ impl<'a> CrateReader<'a> { let loader::Library { dylib, rlib, metadata } = lib; let cnum_map = self.resolve_crate_deps(root, metadata.as_slice(), cnum, span); - let staged_api = self.is_staged_api(metadata.as_slice()); let cmeta = Rc::new(cstore::CrateMetadata { name: name.to_string(), @@ -332,7 +331,6 @@ impl<'a> CrateReader<'a> { cnum_map: RefCell::new(cnum_map), cnum: cnum, codemap_import_info: RefCell::new(vec![]), - staged_api: staged_api, explicitly_linked: Cell::new(explicitly_linked), }); @@ -352,16 +350,6 @@ impl<'a> CrateReader<'a> { (cnum, cmeta, source) } - fn is_staged_api(&self, data: &[u8]) -> bool { - let attrs = decoder::get_crate_attributes(data); - for attr in &attrs { - if attr.name() == "stable" || attr.name() == "unstable" { - return true - } - } - false - } - fn resolve_crate(&mut self, root: &Option, ident: &str, diff --git a/src/librustc_metadata/csearch.rs b/src/librustc_metadata/csearch.rs index b291c4927aa3f..38b18fa63e3eb 100644 --- a/src/librustc_metadata/csearch.rs +++ b/src/librustc_metadata/csearch.rs @@ -14,11 +14,11 @@ use decoder; use encoder; use loader; -use middle::cstore::{InlinedItem, CrateStore, CrateSource, ChildItem, ExternCrate, DefLike}; +use middle::cstore::{InlinedItem, CrateStore, CrateSource, ChildItem, ExternCrate}; use middle::cstore::{NativeLibraryKind, LinkMeta, LinkagePreference}; use rustc::hir::def; use middle::lang_items; -use rustc::ty::{self, Ty, TyCtxt, VariantKind}; +use rustc::ty::{self, Ty, TyCtxt}; use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX}; use rustc::dep_graph::DepNode; @@ -26,10 +26,9 @@ use rustc::hir::map as hir_map; use rustc::hir::map::DefKey; use rustc::mir::repr::Mir; use rustc::mir::mir_map::MirMap; -use rustc::util::nodemap::{FnvHashMap, NodeSet, DefIdMap}; +use rustc::util::nodemap::{NodeSet, DefIdMap}; use rustc::session::config::PanicStrategy; -use std::rc::Rc; use std::path::PathBuf; use syntax::ast; use syntax::attr; @@ -166,42 +165,27 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { result } - fn implementations_of_trait(&self, def_id: DefId) -> Vec + fn implementations_of_trait(&self, filter: Option) -> Vec { - self.dep_graph.read(DepNode::MetaData(def_id)); + if let Some(def_id) = filter { + self.dep_graph.read(DepNode::MetaData(def_id)); + } let mut result = vec![]; self.iter_crate_data(|_, cdata| { - decoder::each_implementation_for_trait(cdata, def_id, &mut |iid| { + decoder::each_implementation_for_trait(cdata, filter, &mut |iid| { result.push(iid) }) }); result } - fn provided_trait_methods<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) - -> Vec>> - { - self.dep_graph.read(DepNode::MetaData(def)); - let cdata = self.get_crate_data(def.krate); - decoder::get_provided_trait_methods(&cdata, def.index, tcx) - } - - fn trait_item_def_ids(&self, def: DefId) - -> Vec - { - self.dep_graph.read(DepNode::MetaData(def)); - let cdata = self.get_crate_data(def.krate); - decoder::get_trait_item_def_ids(&cdata, def.index) - } - - fn impl_items(&self, impl_def_id: DefId) -> Vec - { - self.dep_graph.read(DepNode::MetaData(impl_def_id)); - let cdata = self.get_crate_data(impl_def_id.krate); - decoder::get_impl_items(&cdata, impl_def_id.index) + fn impl_or_trait_items(&self, def_id: DefId) -> Vec { + self.dep_graph.read(DepNode::MetaData(def_id)); + let cdata = self.get_crate_data(def_id.krate); + decoder::get_impl_or_trait_items(&cdata, def_id.index) } - fn impl_polarity(&self, def: DefId) -> Option + fn impl_polarity(&self, def: DefId) -> hir::ImplPolarity { self.dep_graph.read(DepNode::MetaData(def)); let cdata = self.get_crate_data(def.krate); @@ -224,14 +208,6 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { decoder::get_custom_coerce_unsized_kind(&cdata, def.index) } - // FIXME: killme - fn associated_consts<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) - -> Vec>> { - self.dep_graph.read(DepNode::MetaData(def)); - let cdata = self.get_crate_data(def.krate); - decoder::get_associated_consts(&cdata, def.index, tcx) - } - fn impl_parent(&self, impl_def: DefId) -> Option { self.dep_graph.read(DepNode::MetaData(impl_def)); let cdata = self.get_crate_data(impl_def.krate); @@ -266,13 +242,6 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { decoder::is_defaulted_trait(&cdata, trait_def_id.index) } - fn is_impl(&self, did: DefId) -> bool - { - self.dep_graph.read(DepNode::MetaData(did)); - let cdata = self.get_crate_data(did.krate); - decoder::is_impl(&cdata, did.index) - } - fn is_default_impl(&self, impl_did: DefId) -> bool { self.dep_graph.read(DepNode::MetaData(impl_did)); let cdata = self.get_crate_data(impl_did.krate); @@ -295,12 +264,6 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { self.do_is_statically_included_foreign_item(id) } - fn is_typedef(&self, did: DefId) -> bool { - self.dep_graph.read(DepNode::MetaData(did)); - let cdata = self.get_crate_data(did.krate); - decoder::is_typedef(&cdata, did.index) - } - fn dylib_dependency_formats(&self, cnum: CrateNum) -> Vec<(CrateNum, LinkagePreference)> { @@ -310,12 +273,8 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { fn lang_items(&self, cnum: CrateNum) -> Vec<(DefIndex, usize)> { - let mut result = vec![]; let crate_data = self.get_crate_data(cnum); - decoder::each_lang_item(&crate_data, |did, lid| { - result.push((did, lid)); true - }); - result + decoder::get_lang_items(&crate_data) } fn missing_lang_items(&self, cnum: CrateNum) @@ -327,7 +286,7 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { fn is_staged_api(&self, cnum: CrateNum) -> bool { - self.get_crate_data(cnum).staged_api + self.get_crate_data(cnum).is_staged_api() } fn is_explicitly_linked(&self, cnum: CrateNum) -> bool @@ -355,7 +314,7 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { fn crate_attrs(&self, cnum: CrateNum) -> Vec { - decoder::get_crate_attributes(self.get_crate_data(cnum).data()) + decoder::get_item_attrs(&self.get_crate_data(cnum), CRATE_DEF_INDEX) } fn crate_name(&self, cnum: CrateNum) -> token::InternedString @@ -382,13 +341,7 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { fn crate_disambiguator(&self, cnum: CrateNum) -> token::InternedString { let cdata = self.get_crate_data(cnum); - token::intern_and_get_ident(decoder::get_crate_disambiguator(cdata.data())) - } - - fn crate_struct_field_attrs(&self, cnum: CrateNum) - -> FnvHashMap> - { - decoder::get_struct_field_attrs(&self.get_crate_data(cnum)) + token::intern_and_get_ident(&decoder::get_crate_disambiguator(cdata.data())) } fn plugin_registrar_fn(&self, cnum: CrateNum) -> Option @@ -447,12 +400,6 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { decoder::def_path(&cdata, def.index) } - fn variant_kind(&self, def_id: DefId) -> Option { - self.dep_graph.read(DepNode::MetaData(def_id)); - let cdata = self.get_crate_data(def_id.krate); - decoder::get_variant_kind(&cdata, def_id.index) - } - fn struct_ctor_def_id(&self, struct_def_id: DefId) -> Option { self.dep_graph.read(DepNode::MetaData(struct_def_id)); @@ -486,17 +433,6 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { result } - fn crate_top_level_items(&self, cnum: CrateNum) -> Vec - { - let mut result = vec![]; - let crate_data = self.get_crate_data(cnum); - let get_crate_data = |cnum| self.get_crate_data(cnum); - decoder::each_top_level_item_of_crate(&crate_data, get_crate_data, |def, name, vis| { - result.push(ChildItem { def: def, name: name, vis: vis }); - }); - result - } - fn maybe_get_item_ast<'a>(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) @@ -726,9 +662,10 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { let mut bfs_queue = &mut VecDeque::new(); let mut add_child = |bfs_queue: &mut VecDeque<_>, child: ChildItem, parent: DefId| { - let child = match child.def { - DefLike::DlDef(def) if child.vis == ty::Visibility::Public => def.def_id(), - _ => return, + let child = if child.vis == ty::Visibility::Public { + child.def.def_id() + } else { + return; }; match visible_parent_map.entry(child) { @@ -746,10 +683,10 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { } }; - let croot = DefId { krate: cnum, index: CRATE_DEF_INDEX }; - for child in self.crate_top_level_items(cnum) { - add_child(bfs_queue, child, croot); - } + bfs_queue.push_back(DefId { + krate: cnum, + index: CRATE_DEF_INDEX + }); while let Some(def) = bfs_queue.pop_front() { for child in self.item_children(def) { add_child(bfs_queue, child, def); @@ -760,4 +697,3 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { visible_parent_map } } - diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index 388620a2dafd3..7aa4677353bb2 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -22,7 +22,7 @@ use index; use loader; use rustc::dep_graph::DepGraph; -use rustc::hir::def_id::{CrateNum, DefIndex, DefId}; +use rustc::hir::def_id::{CRATE_DEF_INDEX, CrateNum, DefIndex, DefId}; use rustc::hir::map::DefKey; use rustc::hir::svh::Svh; use rustc::middle::cstore::ExternCrate; @@ -77,7 +77,6 @@ pub struct CrateMetadata { pub cnum_map: RefCell, pub cnum: CrateNum, pub codemap_import_info: RefCell>, - pub staged_api: bool, pub index: index::Index, pub xref_index: index::DenseIndex, @@ -300,9 +299,9 @@ impl CStore { impl CrateMetadata { pub fn data<'a>(&'a self) -> &'a [u8] { self.data.as_slice() } - pub fn name(&self) -> &str { decoder::get_crate_name(self.data()) } + pub fn name(&self) -> String { decoder::get_crate_name(self.data()) } pub fn hash(&self) -> Svh { decoder::get_crate_hash(self.data()) } - pub fn disambiguator(&self) -> &str { + pub fn disambiguator(&self) -> String { decoder::get_crate_disambiguator(self.data()) } pub fn imported_filemaps<'a>(&'a self, codemap: &codemap::CodeMap) @@ -320,23 +319,30 @@ impl CrateMetadata { } } + pub fn is_staged_api(&self) -> bool { + let attrs = decoder::get_item_attrs(self, CRATE_DEF_INDEX); + attrs.iter().any(|attr| { + attr.name() == "stable" || attr.name() == "unstable" + }) + } + pub fn is_allocator(&self) -> bool { - let attrs = decoder::get_crate_attributes(self.data()); + let attrs = decoder::get_item_attrs(self, CRATE_DEF_INDEX); attr::contains_name(&attrs, "allocator") } pub fn needs_allocator(&self) -> bool { - let attrs = decoder::get_crate_attributes(self.data()); + let attrs = decoder::get_item_attrs(self, CRATE_DEF_INDEX); attr::contains_name(&attrs, "needs_allocator") } pub fn is_panic_runtime(&self) -> bool { - let attrs = decoder::get_crate_attributes(self.data()); + let attrs = decoder::get_item_attrs(self, CRATE_DEF_INDEX); attr::contains_name(&attrs, "panic_runtime") } pub fn needs_panic_runtime(&self) -> bool { - let attrs = decoder::get_crate_attributes(self.data()); + let attrs = decoder::get_item_attrs(self, CRATE_DEF_INDEX); attr::contains_name(&attrs, "needs_panic_runtime") } diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 0118cacad182e..507e6414181b8 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -12,13 +12,11 @@ #![allow(non_camel_case_types)] -use self::Family::*; - use astencode::decode_inlined_item; use cstore::{self, CrateMetadata}; use common::*; +use common::Family::*; use def_key; -use encoder::def_to_u64; use index; use rustc::hir::def_id::CRATE_DEF_INDEX; @@ -31,12 +29,11 @@ use rustc::hir::intravisit::IdRange; use rustc::session::config::PanicStrategy; use middle::cstore::{InlinedItem, LinkagePreference}; -use middle::cstore::{DefLike, DlDef, DlField, DlImpl}; -use rustc::hir::def::Def; +use rustc::hir::def::{self, Def}; use rustc::hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE}; use middle::lang_items; use rustc::ty::{ImplContainer, TraitContainer}; -use rustc::ty::{self, AdtKind, Ty, TyCtxt, TypeFoldable, VariantKind}; +use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc::ty::subst::Substs; use rustc_const_math::ConstInt; @@ -52,12 +49,9 @@ use std::u32; use rbml::reader; use rbml; use rustc_serialize::{Decodable, Decoder, SpecializedDecoder, opaque}; -use rustc_serialize as serialize; use syntax::attr; -use syntax::parse::token; use syntax::ast::{self, NodeId}; -use syntax::print::pprust; -use syntax_pos::{self, Span, BytePos, NO_EXPANSION}; +use syntax_pos::{self, Span, BytePos}; pub struct DecodeContext<'a, 'tcx: 'a> { pub opaque: opaque::Decoder<'a>, @@ -94,6 +88,25 @@ impl<'a, 'tcx> DecodeContext<'a, 'tcx> { pub fn cdata(&self) -> &'a cstore::CrateMetadata { self.cdata.expect("missing CrateMetadata in DecodeContext") } + + pub fn decode(&mut self) -> T { + T::decode(self).unwrap() + } + + /// Iterate over the indices of a sequence. + /// This will work solely because of `serialize::opaque`'s + /// simple encoding of `n: usize` followed by `n` elements. + pub fn seq(mut self) -> impl Iterator { + (0..self.read_usize().unwrap()).map(move |_| { + self.decode() + }) + } + + pub fn seq_mut<'b, T: Decodable>(&'b mut self) -> impl Iterator + 'b { + (0..self.read_usize().unwrap()).map(move |_| { + self.decode() + }) + } } macro_rules! decoder_methods { @@ -104,8 +117,8 @@ macro_rules! decoder_methods { } } -impl<'doc, 'tcx> serialize::Decoder for ::decoder::DecodeContext<'doc, 'tcx> { - type Error = as serialize::Decoder>::Error; +impl<'doc, 'tcx> Decoder for DecodeContext<'doc, 'tcx> { + type Error = as Decoder>::Error; decoder_methods! { read_nil -> (); @@ -311,175 +324,70 @@ impl CrateMetadata { } pub fn load_index(data: &[u8]) -> index::Index { - let index = reader::get_doc(rbml::Doc::new(data), tag_index); - index::Index::from_rbml(index) + index::Index::from_rbml(rbml::Doc::new(data).get(tag_index)) } pub fn crate_rustc_version(data: &[u8]) -> Option { let doc = rbml::Doc::new(data); - reader::maybe_get_doc(doc, tag_rustc_version).map(|s| s.to_string()) + reader::maybe_get_doc(doc, tag_rustc_version).map(|s| { + str::from_utf8(&s.data[s.start..s.end]).unwrap().to_string() + }) } pub fn load_xrefs(data: &[u8]) -> index::DenseIndex { - let index = reader::get_doc(rbml::Doc::new(data), tag_xref_index); + let index = rbml::Doc::new(data).get(tag_xref_index); index::DenseIndex::from_buf(index.data, index.start, index.end) } // Go through each item in the metadata and create a map from that // item's def-key to the item's DefIndex. pub fn load_key_map(data: &[u8]) -> FnvHashMap { - let root_doc = rbml::Doc::new(data); - let items_doc = reader::get_doc(root_doc, tag_items); - let items_data_doc = reader::get_doc(items_doc, tag_items_data); - reader::docs(items_data_doc) - .filter(|&(tag, _)| tag == tag_items_data_item) - .map(|(_, item_doc)| { - // load def-key from item - let key = item_def_key(item_doc); - - // load def-index from item; we only encode the full def-id, - // so just pull out the index - let def_id_doc = reader::get_doc(item_doc, tag_def_id); - let def_id = untranslated_def_id(def_id_doc); - assert!(def_id.is_local()); // local to the crate we are decoding, that is - - (key, def_id.index) - }) - .collect() -} - -#[derive(Clone, Copy, Debug, PartialEq)] -enum Family { - ImmStatic, // c - MutStatic, // b - Fn, // f - StaticMethod, // F - Method, // h - Type, // y - Mod, // m - ForeignMod, // n - Enum, // t - Variant(VariantKind), // V, v, w - Impl, // i - DefaultImpl, // d - Trait, // I - Struct(VariantKind), // S, s, u - Union, // U - PublicField, // g - InheritedField, // N - Constant, // C + rbml::Doc::new(data).get(tag_items).get(tag_items_data).children().map(|item_doc| { + // load def-key from item + let key = item_def_key(item_doc); + + // load def-index from item + (key, item_doc.get(tag_def_index).decoder().decode()) + }).collect() } fn item_family(item: rbml::Doc) -> Family { - let fam = reader::get_doc(item, tag_items_data_item_family); - match reader::doc_as_u8(fam) as char { - 'C' => Constant, - 'c' => ImmStatic, - 'b' => MutStatic, - 'f' => Fn, - 'F' => StaticMethod, - 'h' => Method, - 'y' => Type, - 'm' => Mod, - 'n' => ForeignMod, - 't' => Enum, - 'V' => Variant(VariantKind::Struct), - 'v' => Variant(VariantKind::Tuple), - 'w' => Variant(VariantKind::Unit), - 'i' => Impl, - 'd' => DefaultImpl, - 'I' => Trait, - 'S' => Struct(VariantKind::Struct), - 's' => Struct(VariantKind::Tuple), - 'u' => Struct(VariantKind::Unit), - 'U' => Union, - 'g' => PublicField, - 'N' => InheritedField, - c => bug!("unexpected family char: {}", c) - } + item.get(tag_items_data_item_family).decoder().decode() } fn item_visibility(item: rbml::Doc) -> ty::Visibility { match reader::maybe_get_doc(item, tag_items_data_item_visibility) { None => ty::Visibility::Public, - Some(visibility_doc) => { - match reader::doc_as_u8(visibility_doc) as char { - 'y' => ty::Visibility::Public, - 'i' => ty::Visibility::PrivateExternal, - _ => bug!("unknown visibility character") - } - } - } -} - -fn fn_constness(item: rbml::Doc) -> hir::Constness { - match reader::maybe_get_doc(item, tag_items_data_item_constness) { - None => hir::Constness::NotConst, - Some(constness_doc) => { - match reader::doc_as_u8(constness_doc) as char { - 'c' => hir::Constness::Const, - 'n' => hir::Constness::NotConst, - _ => bug!("unknown constness character") - } - } + Some(visibility_doc) => visibility_doc.decoder().decode() } } fn item_defaultness(item: rbml::Doc) -> hir::Defaultness { match reader::maybe_get_doc(item, tag_items_data_item_defaultness) { None => hir::Defaultness::Default, // should occur only for default impls on traits - Some(defaultness_doc) => { - match reader::doc_as_u8(defaultness_doc) as char { - 'd' => hir::Defaultness::Default, - 'f' => hir::Defaultness::Final, - _ => bug!("unknown defaultness character") - } - } - } -} - -fn item_sort(item: rbml::Doc) -> Option { - reader::tagged_docs(item, tag_item_trait_item_sort).nth(0).map(|doc| { - doc.as_str().as_bytes()[0] as char - }) -} - -fn untranslated_def_id(d: rbml::Doc) -> DefId { - let id = reader::doc_as_u64(d); - DefId { - krate: CrateNum::from_u32((id >> 32) as u32), - index: DefIndex::from_u32((id & 0xFFFF_FFFF) as u32) + Some(defaultness_doc) => defaultness_doc.decoder().decode() } } -fn translated_def_id(cdata: Cmd, d: rbml::Doc) -> DefId { - let def_id = untranslated_def_id(d); - translate_def_id(cdata, def_id) -} - fn item_parent_item(cdata: Cmd, d: rbml::Doc) -> Option { - reader::tagged_docs(d, tag_items_data_parent_item).nth(0).map(|did| { - translated_def_id(cdata, did) + reader::maybe_get_doc(d, tag_items_data_parent_item).map(|did| { + let mut dcx = did.decoder(); + dcx.cdata = Some(cdata); + dcx.decode() }) } fn item_require_parent_item(cdata: Cmd, d: rbml::Doc) -> DefId { - translated_def_id(cdata, reader::get_doc(d, tag_items_data_parent_item)) + let mut dcx = d.get(tag_items_data_parent_item).decoder(); + dcx.cdata = Some(cdata); + dcx.decode() } fn item_def_id(d: rbml::Doc, cdata: Cmd) -> DefId { - translated_def_id(cdata, reader::get_doc(d, tag_def_id)) -} - -fn reexports<'a>(d: rbml::Doc<'a>) -> reader::TaggedDocsIterator<'a> { - reader::tagged_docs(d, tag_items_data_item_reexport) -} - -fn variant_disr_val(d: rbml::Doc) -> u64 { - let val_doc = reader::get_doc(d, tag_disr_val); - reader::with_doc_data(val_doc, |data| { - str::from_utf8(data).unwrap().parse().unwrap() - }) + DefId { + krate: cdata.cnum, + index: d.get(tag_def_index).decoder().decode() + } } fn doc_type<'a, 'tcx>(doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>, cdata: Cmd) -> Ty<'tcx> { @@ -492,7 +400,7 @@ fn maybe_doc_type<'a, 'tcx>(doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>, cdata: let mut dcx = tp.decoder(); dcx.tcx = Some(tcx); dcx.cdata = Some(cdata); - Decodable::decode(&mut dcx).unwrap() + dcx.decode() }) } @@ -501,13 +409,7 @@ fn doc_trait_ref<'a, 'tcx>(doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>, cdata: C let mut dcx = doc.decoder(); dcx.tcx = Some(tcx); dcx.cdata = Some(cdata); - Decodable::decode(&mut dcx).unwrap() -} - -fn item_trait_ref<'a, 'tcx>(doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>, cdata: Cmd) - -> ty::TraitRef<'tcx> { - let tp = reader::get_doc(doc, tag_item_trait_ref); - doc_trait_ref(tp, tcx, cdata) + dcx.decode() } fn item_name(item: rbml::Doc) -> ast::Name { @@ -516,95 +418,43 @@ fn item_name(item: rbml::Doc) -> ast::Name { fn maybe_item_name(item: rbml::Doc) -> Option { reader::maybe_get_doc(item, tag_paths_data_name).map(|name| { - let string = name.as_str(); - token::intern(string) + name.decoder().decode() }) } -fn family_to_variant_kind<'tcx>(family: Family) -> Option { - match family { - Struct(VariantKind::Struct) | Variant(VariantKind::Struct) | Union => - Some(ty::VariantKind::Struct), - Struct(VariantKind::Tuple) | Variant(VariantKind::Tuple) => - Some(ty::VariantKind::Tuple), - Struct(VariantKind::Unit) | Variant(VariantKind::Unit) => - Some(ty::VariantKind::Unit), - _ => None, - } -} - -fn item_to_def_like(cdata: Cmd, item: rbml::Doc, did: DefId) -> DefLike { - let fam = item_family(item); - match fam { - Constant => { - // Check whether we have an associated const item. - match item_sort(item) { - Some('C') | Some('c') => { - DlDef(Def::AssociatedConst(did)) - } - _ => { - // Regular const item. - DlDef(Def::Const(did)) - } - } - } - ImmStatic => DlDef(Def::Static(did, false)), - MutStatic => DlDef(Def::Static(did, true)), - Struct(..) => DlDef(Def::Struct(did)), - Union => DlDef(Def::Union(did)), - Fn => DlDef(Def::Fn(did)), - Method | StaticMethod => { - DlDef(Def::Method(did)) +fn item_to_def(cdata: Cmd, item: rbml::Doc, did: DefId) -> Option { + Some(match item_family(item) { + Family::Const => Def::Const(did), + Family::AssociatedConst => Def::AssociatedConst(did), + Family::ImmStatic => Def::Static(did, false), + Family::MutStatic => Def::Static(did, true), + Family::Struct(..) => Def::Struct(did), + Family::Union => Def::Union(did), + Family::Fn => Def::Fn(did), + Family::Method => Def::Method(did), + Family::Type => Def::TyAlias(did), + Family::AssociatedType => { + Def::AssociatedTy(item_require_parent_item(cdata, item), did) } - Type => { - if item_sort(item) == Some('t') { - let trait_did = item_require_parent_item(cdata, item); - DlDef(Def::AssociatedTy(trait_did, did)) - } else { - DlDef(Def::TyAlias(did)) - } + Family::Mod => Def::Mod(did), + Family::ForeignMod => Def::ForeignMod(did), + Family::Variant(..) => { + Def::Variant(item_require_parent_item(cdata, item), did) } - Mod => DlDef(Def::Mod(did)), - ForeignMod => DlDef(Def::ForeignMod(did)), - Variant(..) => { - let enum_did = item_require_parent_item(cdata, item); - DlDef(Def::Variant(enum_did, did)) + Family::Trait => Def::Trait(did), + Family::Enum => Def::Enum(did), + + Family::Impl | + Family::DefaultImpl | + Family::PublicField | + Family::InheritedField => { + return None } - Trait => DlDef(Def::Trait(did)), - Enum => DlDef(Def::Enum(did)), - Impl | DefaultImpl => DlImpl(did), - PublicField | InheritedField => DlField, - } -} - -fn parse_unsafety(item_doc: rbml::Doc) -> hir::Unsafety { - let unsafety_doc = reader::get_doc(item_doc, tag_unsafety); - if reader::doc_as_u8(unsafety_doc) != 0 { - hir::Unsafety::Unsafe - } else { - hir::Unsafety::Normal - } -} - -fn parse_paren_sugar(item_doc: rbml::Doc) -> bool { - let paren_sugar_doc = reader::get_doc(item_doc, tag_paren_sugar); - reader::doc_as_u8(paren_sugar_doc) != 0 -} - -fn parse_polarity(item_doc: rbml::Doc) -> hir::ImplPolarity { - let polarity_doc = reader::get_doc(item_doc, tag_polarity); - if reader::doc_as_u8(polarity_doc) != 0 { - hir::ImplPolarity::Negative - } else { - hir::ImplPolarity::Positive - } + }) } fn parse_associated_type_names(item_doc: rbml::Doc) -> Vec { - let names_doc = reader::get_doc(item_doc, tag_associated_type_names); - reader::tagged_docs(names_doc, tag_associated_type_name) - .map(|name_doc| token::intern(name_doc.as_str())) - .collect() + item_doc.get(tag_associated_type_names).decoder().decode() } pub fn get_trait_def<'a, 'tcx>(cdata: Cmd, @@ -613,15 +463,16 @@ pub fn get_trait_def<'a, 'tcx>(cdata: Cmd, { let item_doc = cdata.lookup_item(item_id); let generics = doc_generics(item_doc, tcx, cdata); - let unsafety = parse_unsafety(item_doc); + let unsafety = item_doc.get(tag_unsafety).decoder().decode(); let associated_type_names = parse_associated_type_names(item_doc); - let paren_sugar = parse_paren_sugar(item_doc); + let paren_sugar = item_doc.get(tag_paren_sugar).decoder().decode(); + let trait_ref = doc_trait_ref(item_doc.get(tag_item_trait_ref), tcx, cdata); let def_path = def_path(cdata, item_id).unwrap(); ty::TraitDef::new(unsafety, paren_sugar, generics, - item_trait_ref(item_doc, tcx, cdata), + trait_ref, associated_type_names, def_path.deterministic_hash(tcx)) } @@ -632,16 +483,19 @@ pub fn get_adt_def<'a, 'tcx>(cdata: Cmd, -> ty::AdtDefMaster<'tcx> { fn expect_variant_kind(family: Family) -> ty::VariantKind { - match family_to_variant_kind(family) { - Some(kind) => kind, + match family { + Struct(kind) | Variant(kind) => kind, + Union => ty::VariantKind::Struct, _ => bug!("unexpected family: {:?}", family), } } fn get_enum_variants<'tcx>(cdata: Cmd, doc: rbml::Doc) -> Vec> { - reader::tagged_docs(doc, tag_items_data_item_variant).map(|p| { - let did = translated_def_id(cdata, p); + let mut dcx = doc.get(tag_mod_children).decoder(); + dcx.cdata = Some(cdata); + + dcx.seq().map(|did: DefId| { let item = cdata.lookup_item(did.index); - let disr = variant_disr_val(item); + let disr = item.get(tag_disr_val).decoder().decode(); ty::VariantDefData { did: did, name: item_name(item), @@ -652,23 +506,18 @@ pub fn get_adt_def<'a, 'tcx>(cdata: Cmd, }).collect() } fn get_variant_fields<'tcx>(cdata: Cmd, doc: rbml::Doc) -> Vec> { - let mut index = 0; - reader::tagged_docs(doc, tag_item_field).map(|f| { - let ff = item_family(f); - match ff { - PublicField | InheritedField => {}, - _ => bug!("expected field, found {:?}", ff) + let mut dcx = doc.get(tag_item_fields).decoder(); + dcx.cdata = Some(cdata); + + dcx.seq().map(|did: DefId| { + let f = cdata.lookup_item(did.index); + let vis = match item_family(f) { + PublicField => ty::Visibility::Public, + InheritedField => ty::Visibility::PrivateExternal, + _ => bug!() }; - ty::FieldDefData::new(item_def_id(f, cdata), - item_name(f), - struct_field_family_to_visibility(ff)) - }).chain(reader::tagged_docs(doc, tag_item_unnamed_field).map(|f| { - let ff = item_family(f); - let name = token::with_ident_interner(|interner| interner.intern(index.to_string())); - index += 1; - ty::FieldDefData::new(item_def_id(f, cdata), name, - struct_field_family_to_visibility(ff)) - })).collect() + ty::FieldDefData::new(did, item_name(f), vis) + }).collect() } fn get_struct_variant<'tcx>(cdata: Cmd, doc: rbml::Doc, @@ -692,7 +541,9 @@ pub fn get_adt_def<'a, 'tcx>(cdata: Cmd, Struct(..) => { // Use separate constructor id for unit/tuple structs and reuse did for braced structs. ctor_did = reader::maybe_get_doc(doc, tag_items_data_item_struct_ctor).map(|ctor_doc| { - translated_def_id(cdata, ctor_doc) + let mut dcx = ctor_doc.decoder(); + dcx.cdata = Some(cdata); + dcx.decode() }); (AdtKind::Struct, vec![get_struct_variant(cdata, doc, ctor_did.unwrap_or(did))]) } @@ -784,14 +635,14 @@ pub fn get_type<'a, 'tcx>(cdata: Cmd, id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) pub fn get_stability(cdata: Cmd, id: DefIndex) -> Option { let item = cdata.lookup_item(id); reader::maybe_get_doc(item, tag_items_data_item_stability).map(|doc| { - Decodable::decode(&mut doc.decoder()).unwrap() + doc.decoder().decode() }) } pub fn get_deprecation(cdata: Cmd, id: DefIndex) -> Option { let item = cdata.lookup_item(id); reader::maybe_get_doc(item, tag_items_data_item_deprecation).map(|doc| { - Decodable::decode(&mut doc.decoder()).unwrap() + doc.decoder().decode() }) } @@ -802,26 +653,21 @@ pub fn get_visibility(cdata: Cmd, id: DefIndex) -> ty::Visibility { pub fn get_parent_impl(cdata: Cmd, id: DefIndex) -> Option { let item = cdata.lookup_item(id); reader::maybe_get_doc(item, tag_items_data_parent_impl).map(|doc| { - translated_def_id(cdata, doc) + let mut dcx = doc.decoder(); + dcx.cdata = Some(cdata); + dcx.decode() }) } pub fn get_repr_attrs(cdata: Cmd, id: DefIndex) -> Vec { let item = cdata.lookup_item(id); reader::maybe_get_doc(item, tag_items_data_item_repr).map_or(vec![], |doc| { - Decodable::decode(&mut doc.decoder()).unwrap() + doc.decoder().decode() }) } -pub fn get_impl_polarity(cdata: Cmd, id: DefIndex) -> Option { - let item_doc = cdata.lookup_item(id); - let fam = item_family(item_doc); - match fam { - Family::Impl => { - Some(parse_polarity(item_doc)) - } - _ => None - } +pub fn get_impl_polarity(cdata: Cmd, id: DefIndex) -> hir::ImplPolarity { + cdata.lookup_item(id).get(tag_polarity).decoder().decode() } pub fn get_custom_coerce_unsized_kind( @@ -831,7 +677,7 @@ pub fn get_custom_coerce_unsized_kind( { let item_doc = cdata.lookup_item(id); reader::maybe_get_doc(item_doc, tag_impl_coerce_unsized_kind).map(|kind_doc| { - Decodable::decode(&mut kind_doc.decoder()).unwrap() + kind_doc.decoder().decode() }) } @@ -841,44 +687,38 @@ pub fn get_impl_trait<'a, 'tcx>(cdata: Cmd, -> Option> { let item_doc = cdata.lookup_item(id); - let fam = item_family(item_doc); - match fam { - Family::Impl | Family::DefaultImpl => { - reader::maybe_get_doc(item_doc, tag_item_trait_ref).map(|tp| { - doc_trait_ref(tp, tcx, cdata) - }) - } - _ => None - } + reader::maybe_get_doc(item_doc, tag_item_trait_ref).map(|tp| { + doc_trait_ref(tp, tcx, cdata) + }) } /// Iterates over the language items in the given crate. -pub fn each_lang_item(cdata: Cmd, mut f: F) -> bool where - F: FnMut(DefIndex, usize) -> bool, -{ - let root = rbml::Doc::new(cdata.data()); - let lang_items = reader::get_doc(root, tag_lang_items); - reader::tagged_docs(lang_items, tag_lang_items_item).all(|item_doc| { - let id_doc = reader::get_doc(item_doc, tag_lang_items_item_id); - let id = reader::doc_as_u32(id_doc) as usize; - let index_doc = reader::get_doc(item_doc, tag_lang_items_item_index); - let index = DefIndex::from_u32(reader::doc_as_u32(index_doc)); - - f(index, id) - }) +pub fn get_lang_items(cdata: Cmd) -> Vec<(DefIndex, usize)> { + rbml::Doc::new(cdata.data()).get(tag_lang_items).decoder().decode() } -fn each_child_of_item_or_crate(cdata: Cmd, - item_doc: rbml::Doc, - mut get_crate_data: G, - mut callback: F) where - F: FnMut(DefLike, ast::Name, ty::Visibility), - G: FnMut(CrateNum) -> Rc, + +/// Iterates over each child of the given item. +pub fn each_child_of_item(cdata: Cmd, id: DefIndex, + mut get_crate_data: G, + mut callback: F) + where F: FnMut(Def, ast::Name, ty::Visibility), + G: FnMut(CrateNum) -> Rc, { - // Iterate over all children. - for child_info_doc in reader::tagged_docs(item_doc, tag_mod_child) { - let child_def_id = translated_def_id(cdata, child_info_doc); + // Find the item. + let item_doc = match cdata.get_item(id) { + None => return, + Some(item_doc) => item_doc, + }; + + let mut dcx = match reader::maybe_get_doc(item_doc, tag_mod_children) { + Some(doc) => doc.decoder(), + None => return + }; + dcx.cdata = Some(cdata); + // Iterate over all children. + for child_def_id in dcx.seq_mut::() { // This item may be in yet another crate if it was the child of a // reexport. let crate_data = if child_def_id.krate == cdata.cnum { @@ -894,27 +734,20 @@ fn each_child_of_item_or_crate(cdata: Cmd, // Get the item. if let Some(child_item_doc) = crate_data.get_item(child_def_id.index) { // Hand off the item to the callback. - let child_name = item_name(child_item_doc); - let def_like = item_to_def_like(crate_data, child_item_doc, child_def_id); - let visibility = item_visibility(child_item_doc); - callback(def_like, child_name, visibility); + if let Some(def) = item_to_def(crate_data, child_item_doc, child_def_id) { + let child_name = item_name(child_item_doc); + let visibility = item_visibility(child_item_doc); + callback(def, child_name, visibility); + } } } - for reexport_doc in reexports(item_doc) { - let def_id_doc = reader::get_doc(reexport_doc, - tag_items_data_item_reexport_def_id); - let child_def_id = translated_def_id(cdata, def_id_doc); - - let name_doc = reader::get_doc(reexport_doc, - tag_items_data_item_reexport_name); - let name = name_doc.as_str(); - + for exp in dcx.seq_mut::() { // This reexport may be in yet another crate. - let crate_data = if child_def_id.krate == cdata.cnum { + let crate_data = if exp.def_id.krate == cdata.cnum { None } else { - Some(get_crate_data(child_def_id.krate)) + Some(get_crate_data(exp.def_id.krate)) }; let crate_data = match crate_data { Some(ref cdata) => &**cdata, @@ -922,38 +755,17 @@ fn each_child_of_item_or_crate(cdata: Cmd, }; // Get the item. - if let Some(child_item_doc) = crate_data.get_item(child_def_id.index) { + if let Some(child_item_doc) = crate_data.get_item(exp.def_id.index) { // Hand off the item to the callback. - let def_like = item_to_def_like(crate_data, child_item_doc, child_def_id); - // These items have a public visibility because they're part of - // a public re-export. - callback(def_like, token::intern(name), ty::Visibility::Public); + if let Some(def) = item_to_def(crate_data, child_item_doc, exp.def_id) { + // These items have a public visibility because they're part of + // a public re-export. + callback(def, exp.name, ty::Visibility::Public); + } } } } -/// Iterates over each child of the given item. -pub fn each_child_of_item(cdata: Cmd, id: DefIndex, get_crate_data: G, callback: F) - where F: FnMut(DefLike, ast::Name, ty::Visibility), - G: FnMut(CrateNum) -> Rc, -{ - // Find the item. - let item_doc = match cdata.get_item(id) { - None => return, - Some(item_doc) => item_doc, - }; - - each_child_of_item_or_crate(cdata, item_doc, get_crate_data, callback) -} - -/// Iterates over all the top-level crate items. -pub fn each_top_level_item_of_crate(cdata: Cmd, get_crate_data: G, callback: F) - where F: FnMut(DefLike, ast::Name, ty::Visibility), - G: FnMut(CrateNum) -> Rc, -{ - each_child_of_item(cdata, CRATE_DEF_INDEX, get_crate_data, callback) -} - pub fn get_item_name(cdata: Cmd, id: DefIndex) -> ast::Name { item_name(cdata.lookup_item(id)) } @@ -1030,48 +842,31 @@ pub fn maybe_get_item_mir<'a, 'tcx>(cdata: Cmd, let mut dcx = mir_doc.decoder(); dcx.tcx = Some(tcx); dcx.cdata = Some(cdata); - Decodable::decode(&mut dcx).unwrap() + dcx.decode() }) } -fn get_explicit_self<'a, 'tcx>(item: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>) +fn get_explicit_self<'a, 'tcx>(cdata: Cmd, item: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ty::ExplicitSelfCategory<'tcx> { - fn get_mutability(ch: u8) -> hir::Mutability { - match ch as char { - 'i' => hir::MutImmutable, - 'm' => hir::MutMutable, - _ => bug!("unknown mutability character: `{}`", ch as char), - } - } + let mut dcx = item.get(tag_item_trait_method_explicit_self).decoder(); + dcx.cdata = Some(cdata); + dcx.tcx = Some(tcx); - let explicit_self_doc = reader::get_doc(item, tag_item_trait_method_explicit_self); - let string = explicit_self_doc.as_str(); - - let explicit_self_kind = string.as_bytes()[0]; - match explicit_self_kind as char { - 's' => ty::ExplicitSelfCategory::Static, - 'v' => ty::ExplicitSelfCategory::ByValue, - '~' => ty::ExplicitSelfCategory::ByBox, - // FIXME(#4846) expl. region - '&' => { - ty::ExplicitSelfCategory::ByReference( - tcx.mk_region(ty::ReEmpty), - get_mutability(string.as_bytes()[1])) - } - _ => bug!("unknown self type code: `{}`", explicit_self_kind as char) - } + dcx.decode() } /// Returns the def IDs of all the items in the given implementation. -pub fn get_impl_items(cdata: Cmd, impl_id: DefIndex) - -> Vec { - reader::tagged_docs(cdata.lookup_item(impl_id), tag_item_impl_item).map(|doc| { - let def_id = item_def_id(doc, cdata); - match item_sort(doc) { - Some('C') | Some('c') => ty::ConstTraitItemId(def_id), - Some('r') | Some('p') => ty::MethodTraitItemId(def_id), - Some('t') => ty::TypeTraitItemId(def_id), - _ => bug!("unknown impl item sort"), +pub fn get_impl_or_trait_items(cdata: Cmd, impl_id: DefIndex) + -> Vec { + let item = cdata.lookup_item(impl_id); + let mut dcx = item.get(tag_mod_children).decoder(); + dcx.cdata = Some(cdata); + dcx.seq().map(|def_id: DefId| { + match item_to_def(cdata, cdata.lookup_item(def_id.index), def_id) { + Some(Def::AssociatedConst(def_id)) => ty::ConstTraitItemId(def_id), + Some(Def::Method(def_id)) => ty::MethodTraitItemId(def_id), + Some(Def::AssociatedTy(_, def_id)) => ty::TypeTraitItemId(def_id), + def => bug!("get_impl_or_trait_items: invalid def {:?}", def) } }).collect() } @@ -1092,8 +887,7 @@ pub fn get_impl_or_trait_item<'a, 'tcx>(cdata: Cmd, id: DefIndex, tcx: TyCtxt<'a } else { return None; }; - let container_doc = cdata.lookup_item(container_id.index); - let container = match item_family(container_doc) { + let container = match item_family(cdata.lookup_item(container_id.index)) { Trait => TraitContainer(container_id), _ => ImplContainer(container_id), }; @@ -1102,8 +896,8 @@ pub fn get_impl_or_trait_item<'a, 'tcx>(cdata: Cmd, id: DefIndex, tcx: TyCtxt<'a let vis = item_visibility(item_doc); let defaultness = item_defaultness(item_doc); - Some(match item_sort(item_doc) { - sort @ Some('C') | sort @ Some('c') => { + Some(match item_family(item_doc) { + Family::AssociatedConst => { let ty = doc_type(item_doc, tcx, cdata); ty::ConstTraitItem(Rc::new(ty::AssociatedConst { name: name, @@ -1112,10 +906,10 @@ pub fn get_impl_or_trait_item<'a, 'tcx>(cdata: Cmd, id: DefIndex, tcx: TyCtxt<'a defaultness: defaultness, def_id: def_id, container: container, - has_value: sort == Some('C') + has_value: item_doc.get(tag_item_trait_item_has_body).decoder().decode(), })) } - Some('r') | Some('p') => { + Family::Method => { let generics = doc_generics(item_doc, tcx, cdata); let predicates = doc_predicates(item_doc, tcx, cdata, tag_item_predicates); let ity = tcx.lookup_item_type(def_id).ty; @@ -1125,19 +919,22 @@ pub fn get_impl_or_trait_item<'a, 'tcx>(cdata: Cmd, id: DefIndex, tcx: TyCtxt<'a "the type {:?} of the method {:?} is not a function?", ity, name) }; - let explicit_self = get_explicit_self(item_doc, tcx); - - ty::MethodTraitItem(Rc::new(ty::Method::new(name, - generics, - predicates, - fty, - explicit_self, - vis, - defaultness, - def_id, - container))) + let explicit_self = get_explicit_self(cdata, item_doc, tcx); + + ty::MethodTraitItem(Rc::new(ty::Method { + name: name, + generics: generics, + predicates: predicates, + fty: fty, + explicit_self: explicit_self, + vis: vis, + defaultness: defaultness, + has_body: item_doc.get(tag_item_trait_item_has_body).decoder().decode(), + def_id: def_id, + container: container, + })) } - Some('t') => { + Family::AssociatedType => { let ty = maybe_doc_type(item_doc, tcx, cdata); ty::TypeTraitItem(Rc::new(ty::AssociatedType { name: name, @@ -1152,84 +949,19 @@ pub fn get_impl_or_trait_item<'a, 'tcx>(cdata: Cmd, id: DefIndex, tcx: TyCtxt<'a }) } -pub fn get_trait_item_def_ids(cdata: Cmd, id: DefIndex) - -> Vec { - let item = cdata.lookup_item(id); - reader::tagged_docs(item, tag_item_trait_item).map(|mth| { - let def_id = item_def_id(mth, cdata); - match item_sort(mth) { - Some('C') | Some('c') => ty::ConstTraitItemId(def_id), - Some('r') | Some('p') => ty::MethodTraitItemId(def_id), - Some('t') => ty::TypeTraitItemId(def_id), - _ => bug!("unknown trait item sort"), - } - }).collect() -} - pub fn get_item_variances(cdata: Cmd, id: DefIndex) -> Vec { let item_doc = cdata.lookup_item(id); - let variance_doc = reader::get_doc(item_doc, tag_item_variances); - Decodable::decode(&mut variance_doc.decoder()).unwrap() -} - -pub fn get_provided_trait_methods<'a, 'tcx>(cdata: Cmd, - id: DefIndex, - tcx: TyCtxt<'a, 'tcx, 'tcx>) - -> Vec>> { - let item = cdata.lookup_item(id); - - reader::tagged_docs(item, tag_item_trait_item).filter_map(|mth_id| { - let did = item_def_id(mth_id, cdata); - let mth = cdata.lookup_item(did.index); - - if item_sort(mth) == Some('p') { - let trait_item = get_impl_or_trait_item(cdata, did.index, tcx); - if let Some(ty::MethodTraitItem(ref method)) = trait_item { - Some((*method).clone()) - } else { - None - } - } else { - None - } - }).collect() -} - -pub fn get_associated_consts<'a, 'tcx>(cdata: Cmd, id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) - -> Vec>> { - let item = cdata.lookup_item(id); - - [tag_item_trait_item, tag_item_impl_item].iter().flat_map(|&tag| { - reader::tagged_docs(item, tag).filter_map(|ac_id| { - let did = item_def_id(ac_id, cdata); - let ac_doc = cdata.lookup_item(did.index); - - match item_sort(ac_doc) { - Some('C') | Some('c') => { - let trait_item = get_impl_or_trait_item(cdata, did.index, tcx); - if let Some(ty::ConstTraitItem(ref ac)) = trait_item { - Some((*ac).clone()) - } else { - None - } - } - _ => None - } - }) - }).collect() -} - -pub fn get_variant_kind(cdata: Cmd, node_id: DefIndex) -> Option -{ - let item = cdata.lookup_item(node_id); - family_to_variant_kind(item_family(item)) + item_doc.get(tag_item_variances).decoder().decode() } pub fn get_struct_ctor_def_id(cdata: Cmd, node_id: DefIndex) -> Option { let item = cdata.lookup_item(node_id); - reader::maybe_get_doc(item, tag_items_data_item_struct_ctor). - map(|ctor_doc| translated_def_id(cdata, ctor_doc)) + reader::maybe_get_doc(item, tag_items_data_item_struct_ctor).map(|ctor_doc| { + let mut dcx = ctor_doc.decoder(); + dcx.cdata = Some(cdata); + dcx.decode() + }) } /// If node_id is the constructor of a tuple struct, retrieve the NodeId of @@ -1239,8 +971,12 @@ pub fn get_tuple_struct_definition_if_ctor(cdata: Cmd, -> Option { let item = cdata.lookup_item(node_id); - reader::tagged_docs(item, tag_items_data_item_is_tuple_struct_ctor).next().map(|_| { - item_require_parent_item(cdata, item) + reader::maybe_get_doc(item, tag_items_data_item_is_tuple_struct_ctor).and_then(|doc| { + if doc.decoder().decode() { + Some(item_require_parent_item(cdata, item)) + } else { + None + } }) } @@ -1256,39 +992,18 @@ pub fn get_item_attrs(cdata: Cmd, get_attributes(item) } -pub fn get_struct_field_attrs(cdata: Cmd) -> FnvHashMap> { - let data = rbml::Doc::new(cdata.data()); - let fields = reader::get_doc(data, tag_struct_fields); - reader::tagged_docs(fields, tag_struct_field).map(|field| { - let def_id = translated_def_id(cdata, reader::get_doc(field, tag_def_id)); - let attrs = get_attributes(field); - (def_id, attrs) - }).collect() -} - -fn struct_field_family_to_visibility(family: Family) -> ty::Visibility { - match family { - PublicField => ty::Visibility::Public, - InheritedField => ty::Visibility::PrivateExternal, - _ => bug!() - } -} - pub fn get_struct_field_names(cdata: Cmd, id: DefIndex) -> Vec { - let item = cdata.lookup_item(id); - let mut index = 0; - reader::tagged_docs(item, tag_item_field).map(|an_item| { - item_name(an_item) - }).chain(reader::tagged_docs(item, tag_item_unnamed_field).map(|_| { - let name = token::with_ident_interner(|interner| interner.intern(index.to_string())); - index += 1; - name - })).collect() + let mut dcx = cdata.lookup_item(id).get(tag_item_fields).decoder(); + dcx.cdata = Some(cdata); + + dcx.seq().map(|did: DefId| { + item_name(cdata.lookup_item(did.index)) + }).collect() } fn get_attributes(md: rbml::Doc) -> Vec { reader::maybe_get_doc(md, tag_attributes).map_or(vec![], |attrs_doc| { - let mut attrs = Vec::::decode(&mut attrs_doc.decoder()).unwrap(); + let mut attrs = attrs_doc.decoder().decode::>(); // Need new unique IDs: old thread-local IDs won't map to new threads. for attr in attrs.iter_mut() { @@ -1299,22 +1014,6 @@ fn get_attributes(md: rbml::Doc) -> Vec { }) } -fn list_crate_attributes(md: rbml::Doc, hash: &Svh, - out: &mut io::Write) -> io::Result<()> { - write!(out, "=Crate Attributes ({})=\n", *hash)?; - - let r = get_attributes(md); - for attr in &r { - write!(out, "{}\n", pprust::attribute_to_string(attr))?; - } - - write!(out, "\n\n") -} - -pub fn get_crate_attributes(data: &[u8]) -> Vec { - get_attributes(rbml::Doc::new(data)) -} - #[derive(Clone)] pub struct CrateDep { pub cnum: CrateNum, @@ -1324,19 +1023,9 @@ pub struct CrateDep { } pub fn get_crate_deps(data: &[u8]) -> Vec { - let cratedoc = rbml::Doc::new(data); - let depsdoc = reader::get_doc(cratedoc, tag_crate_deps); + let dcx = rbml::Doc::new(data).get(tag_crate_deps).decoder(); - fn docstr(doc: rbml::Doc, tag_: usize) -> String { - let d = reader::get_doc(doc, tag_); - d.as_str().to_string() - } - - reader::tagged_docs(depsdoc, tag_crate_dep).enumerate().map(|(crate_num, depdoc)| { - let name = docstr(depdoc, tag_crate_dep_crate_name); - let hash = Svh::new(reader::doc_as_u64(reader::get_doc(depdoc, tag_crate_dep_hash))); - let doc = reader::get_doc(depdoc, tag_crate_dep_explicitly_linked); - let explicitly_linked = reader::doc_as_u8(doc) != 0; + dcx.seq().enumerate().map(|(crate_num, (name, hash, explicitly_linked))| { CrateDep { cnum: CrateNum::new(crate_num + 1), name: name, @@ -1358,63 +1047,39 @@ fn list_crate_deps(data: &[u8], out: &mut io::Write) -> io::Result<()> { pub fn maybe_get_crate_hash(data: &[u8]) -> Option { let cratedoc = rbml::Doc::new(data); reader::maybe_get_doc(cratedoc, tag_crate_hash).map(|doc| { - Svh::new(reader::doc_as_u64(doc)) + doc.decoder().decode() }) } pub fn get_crate_hash(data: &[u8]) -> Svh { - let cratedoc = rbml::Doc::new(data); - let hashdoc = reader::get_doc(cratedoc, tag_crate_hash); - Svh::new(reader::doc_as_u64(hashdoc)) + rbml::Doc::new(data).get(tag_crate_hash).decoder().decode() } -pub fn maybe_get_crate_name(data: &[u8]) -> Option<&str> { +pub fn maybe_get_crate_name(data: &[u8]) -> Option { let cratedoc = rbml::Doc::new(data); reader::maybe_get_doc(cratedoc, tag_crate_crate_name).map(|doc| { - doc.as_str() + doc.decoder().decode() }) } -pub fn get_crate_disambiguator<'a>(data: &'a [u8]) -> &'a str { - let crate_doc = rbml::Doc::new(data); - let disambiguator_doc = reader::get_doc(crate_doc, tag_crate_disambiguator); - let slice: &'a str = disambiguator_doc.as_str(); - slice +pub fn get_crate_disambiguator(data: &[u8]) -> String { + rbml::Doc::new(data).get(tag_crate_disambiguator).decoder().decode() } pub fn get_crate_triple(data: &[u8]) -> Option { let cratedoc = rbml::Doc::new(data); let triple_doc = reader::maybe_get_doc(cratedoc, tag_crate_triple); - triple_doc.map(|s| s.as_str().to_string()) + triple_doc.map(|s| s.decoder().decode()) } -pub fn get_crate_name(data: &[u8]) -> &str { +pub fn get_crate_name(data: &[u8]) -> String { maybe_get_crate_name(data).expect("no crate name in crate") } pub fn list_crate_metadata(bytes: &[u8], out: &mut io::Write) -> io::Result<()> { - let hash = get_crate_hash(bytes); - let md = rbml::Doc::new(bytes); - list_crate_attributes(md, &hash, out)?; list_crate_deps(bytes, out) } -// Translates a def_id from an external crate to a def_id for the current -// compilation environment. We use this when trying to load types from -// external crates - if those types further refer to types in other crates -// then we must translate the crate number from that encoded in the external -// crate to the correct local crate number. -pub fn translate_def_id(cdata: Cmd, did: DefId) -> DefId { - if did.is_local() { - return DefId { krate: cdata.cnum, index: did.index }; - } - - DefId { - krate: cdata.cnum_map.borrow()[did.krate], - index: did.index - } -} - // Translate a DefId from the current compilation environment to a DefId // for an external crate. fn reverse_translate_def_id(cdata: Cmd, did: DefId) -> Option { @@ -1433,32 +1098,41 @@ pub fn each_inherent_implementation_for_type(cdata: Cmd, where F: FnMut(DefId), { let item_doc = cdata.lookup_item(id); - for impl_doc in reader::tagged_docs(item_doc, tag_items_data_item_inherent_impl) { - if reader::maybe_get_doc(impl_doc, tag_item_trait_ref).is_none() { - callback(item_def_id(impl_doc, cdata)); - } + let mut dcx = item_doc.get(tag_items_data_item_inherent_impls).decoder(); + dcx.cdata = Some(cdata); + + for impl_def_id in dcx.seq() { + callback(impl_def_id); } } pub fn each_implementation_for_trait(cdata: Cmd, - def_id: DefId, + filter: Option, mut callback: F) where F: FnMut(DefId), { // Do a reverse lookup beforehand to avoid touching the crate_num // hash map in the loop below. - if let Some(crate_local_did) = reverse_translate_def_id(cdata, def_id) { - let def_id_u64 = def_to_u64(crate_local_did); + let filter = match filter.map(|def_id| reverse_translate_def_id(cdata, def_id)) { + Some(Some(def_id)) => Some(def_id), + Some(None) => return, + None => None + }; + + // FIXME(eddyb) Make this O(1) instead of O(n). + for trait_doc in rbml::Doc::new(cdata.data()).get(tag_impls).children() { + let mut dcx = trait_doc.decoder(); + dcx.cdata = Some(cdata); - let impls_doc = reader::get_doc(rbml::Doc::new(cdata.data()), tag_impls); - for trait_doc in reader::tagged_docs(impls_doc, tag_impls_trait) { - let trait_def_id = reader::get_doc(trait_doc, tag_def_id); - if reader::doc_as_u64(trait_def_id) != def_id_u64 { + let (krate, index) = dcx.decode(); + if let Some(local_did) = filter { + if (local_did.krate.as_u32(), local_did.index) != (krate, index) { continue; } - for impl_doc in reader::tagged_docs(trait_doc, tag_impls_trait_impl) { - callback(translated_def_id(cdata, impl_doc)); - } + } + + for impl_def_id in dcx.seq() { + callback(impl_def_id); } } } @@ -1479,33 +1153,20 @@ pub fn get_trait_of_item(cdata: Cmd, id: DefIndex) -> Option { pub fn get_native_libraries(cdata: Cmd) -> Vec<(cstore::NativeLibraryKind, String)> { - let libraries = reader::get_doc(rbml::Doc::new(cdata.data()), - tag_native_libraries); - reader::tagged_docs(libraries, tag_native_libraries_lib).map(|lib_doc| { - let kind_doc = reader::get_doc(lib_doc, tag_native_libraries_kind); - let name_doc = reader::get_doc(lib_doc, tag_native_libraries_name); - let kind: cstore::NativeLibraryKind = - cstore::NativeLibraryKind::from_u32(reader::doc_as_u32(kind_doc)).unwrap(); - let name = name_doc.as_str().to_string(); - (kind, name) - }).collect() + rbml::Doc::new(cdata.data()).get(tag_native_libraries).decoder().decode() } pub fn get_plugin_registrar_fn(data: &[u8]) -> Option { reader::maybe_get_doc(rbml::Doc::new(data), tag_plugin_registrar_fn) - .map(|doc| DefIndex::from_u32(reader::doc_as_u32(doc))) + .map(|doc| doc.decoder().decode()) } pub fn each_exported_macro(data: &[u8], mut f: F) where F: FnMut(ast::Name, Vec, Span, String) -> bool, { - let macros = reader::get_doc(rbml::Doc::new(data), tag_macro_defs); - for macro_doc in reader::tagged_docs(macros, tag_macro_def) { - let name = item_name(macro_doc); - let attrs = get_attributes(macro_doc); - let span = get_macro_span(macro_doc); - let body = reader::get_doc(macro_doc, tag_macro_def_body); - if !f(name, attrs, span, body.as_str().to_string()) { + let dcx = rbml::Doc::new(data).get(tag_macro_defs).decoder(); + for (name, attrs, span, body) in dcx.seq() { + if !f(name, attrs, span, body) { break; } } @@ -1513,86 +1174,52 @@ pub fn each_exported_macro(data: &[u8], mut f: F) where pub fn get_derive_registrar_fn(data: &[u8]) -> Option { reader::maybe_get_doc(rbml::Doc::new(data), tag_macro_derive_registrar) - .map(|doc| DefIndex::from_u32(reader::doc_as_u32(doc))) -} - -pub fn get_macro_span(doc: rbml::Doc) -> Span { - let lo_doc = reader::get_doc(doc, tag_macro_def_span_lo); - let lo = BytePos(reader::doc_as_u32(lo_doc)); - let hi_doc = reader::get_doc(doc, tag_macro_def_span_hi); - let hi = BytePos(reader::doc_as_u32(hi_doc)); - return Span { lo: lo, hi: hi, expn_id: NO_EXPANSION }; + .map(|doc| doc.decoder().decode()) } pub fn get_dylib_dependency_formats(cdata: Cmd) -> Vec<(CrateNum, LinkagePreference)> { - let formats = reader::get_doc(rbml::Doc::new(cdata.data()), - tag_dylib_dependency_formats); - let mut result = Vec::new(); - - debug!("found dylib deps: {}", formats.as_str()); - for spec in formats.as_str().split(',') { - if spec.is_empty() { continue } - let mut split = spec.split(':'); - let cnum = split.next().unwrap(); - let link = split.next().unwrap(); - let cnum = CrateNum::new(cnum.parse().unwrap()); - let cnum = cdata.cnum_map.borrow()[cnum]; - result.push((cnum, if link == "d" { - LinkagePreference::RequireDynamic - } else { - LinkagePreference::RequireStatic - })); - } - return result; -} + let dcx = rbml::Doc::new(cdata.data()).get(tag_dylib_dependency_formats).decoder(); -pub fn get_missing_lang_items(cdata: Cmd) - -> Vec -{ - let items = reader::get_doc(rbml::Doc::new(cdata.data()), tag_lang_items); - reader::tagged_docs(items, tag_lang_items_missing).map(|missing_docs| { - lang_items::LangItem::from_u32(reader::doc_as_u32(missing_docs)).unwrap() + dcx.seq::>().enumerate().flat_map(|(i, link)| { + let cnum = CrateNum::new(i + 1); + link.map(|link| (cdata.cnum_map.borrow()[cnum], link)) }).collect() } +pub fn get_missing_lang_items(cdata: Cmd) -> Vec { + rbml::Doc::new(cdata.data()).get(tag_lang_items_missing).decoder().decode() +} + pub fn get_method_arg_names(cdata: Cmd, id: DefIndex) -> Vec { let method_doc = cdata.lookup_item(id); match reader::maybe_get_doc(method_doc, tag_method_argument_names) { - Some(args_doc) => { - reader::tagged_docs(args_doc, tag_method_argument_name).map(|name_doc| { - name_doc.as_str().to_string() - }).collect() - }, + Some(args_doc) => args_doc.decoder().decode(), None => vec![], } } pub fn get_reachable_ids(cdata: Cmd) -> Vec { - let items = reader::get_doc(rbml::Doc::new(cdata.data()), - tag_reachable_ids); - reader::tagged_docs(items, tag_reachable_id).map(|doc| { + let dcx = rbml::Doc::new(cdata.data()).get(tag_reachable_ids).decoder(); + + dcx.seq().map(|index| { DefId { krate: cdata.cnum, - index: DefIndex::from_u32(reader::doc_as_u32(doc)), + index: index, } }).collect() } -pub fn is_typedef(cdata: Cmd, id: DefIndex) -> bool { - let item_doc = cdata.lookup_item(id); - match item_family(item_doc) { - Type => true, - _ => false, - } -} - pub fn is_const_fn(cdata: Cmd, id: DefIndex) -> bool { - let item_doc = cdata.lookup_item(id); - match fn_constness(item_doc) { - hir::Constness::Const => true, - hir::Constness::NotConst => false, + match reader::maybe_get_doc(cdata.lookup_item(id), tag_items_data_item_constness) { + None => false, + Some(doc) => { + match doc.decoder().decode() { + hir::Constness::Const => true, + hir::Constness::NotConst => false, + } + } } } @@ -1628,40 +1255,15 @@ pub fn is_foreign_item(cdata: Cmd, id: DefIndex) -> bool { item_family(parent_item_doc) == ForeignMod } -pub fn is_impl(cdata: Cmd, id: DefIndex) -> bool { - let item_doc = cdata.lookup_item(id); - match item_family(item_doc) { - Impl => true, - _ => false, - } -} - fn doc_generics<'a, 'tcx>(base_doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>, cdata: Cmd) -> &'tcx ty::Generics<'tcx> { - let mut dcx = reader::get_doc(base_doc, tag_item_generics).decoder(); - dcx.tcx = Some(tcx); - dcx.cdata = Some(cdata); - tcx.alloc_generics(Decodable::decode(&mut dcx).unwrap()) -} - -fn doc_predicate<'a, 'tcx>(cdata: Cmd, - doc: rbml::Doc, - tcx: TyCtxt<'a, 'tcx, 'tcx>) - -> ty::Predicate<'tcx> -{ - let predicate_pos = cdata.xref_index.lookup( - cdata.data(), reader::doc_as_u32(doc)).unwrap() as usize; - let mut dcx = rbml::Doc { - data: cdata.data(), - start: predicate_pos, - end: cdata.data().len(), - }.decoder(); + let mut dcx = base_doc.get(tag_item_generics).decoder(); dcx.tcx = Some(tcx); dcx.cdata = Some(cdata); - Decodable::decode(&mut dcx).unwrap() + tcx.alloc_generics(dcx.decode()) } fn doc_predicates<'a, 'tcx>(base_doc: rbml::Doc, @@ -1670,51 +1272,50 @@ fn doc_predicates<'a, 'tcx>(base_doc: rbml::Doc, tag: usize) -> ty::GenericPredicates<'tcx> { - let doc = reader::get_doc(base_doc, tag); + let mut dcx = base_doc.get(tag).decoder(); + dcx.cdata = Some(cdata); ty::GenericPredicates { - parent: item_parent_item(cdata, doc), - predicates: reader::tagged_docs(doc, tag_predicate).map(|predicate_doc| { - doc_predicate(cdata, predicate_doc, tcx) + parent: dcx.decode(), + predicates: dcx.seq().map(|offset| { + let predicate_pos = cdata.xref_index.lookup( + cdata.data(), offset).unwrap() as usize; + let mut dcx = rbml::Doc { + data: cdata.data(), + start: predicate_pos, + end: cdata.data().len(), + }.decoder(); + dcx.tcx = Some(tcx); + dcx.cdata = Some(cdata); + dcx.decode() }).collect() } } pub fn is_defaulted_trait(cdata: Cmd, trait_id: DefIndex) -> bool { - let trait_doc = cdata.lookup_item(trait_id); - assert!(item_family(trait_doc) == Family::Trait); - let defaulted_doc = reader::get_doc(trait_doc, tag_defaulted_trait); - reader::doc_as_u8(defaulted_doc) != 0 + cdata.lookup_item(trait_id).get(tag_defaulted_trait).decoder().decode() } pub fn is_default_impl(cdata: Cmd, impl_id: DefIndex) -> bool { - let impl_doc = cdata.lookup_item(impl_id); - item_family(impl_doc) == Family::DefaultImpl + item_family(cdata.lookup_item(impl_id)) == Family::DefaultImpl } pub fn get_imported_filemaps(metadata: &[u8]) -> Vec { - let crate_doc = rbml::Doc::new(metadata); - let cm_doc = reader::get_doc(crate_doc, tag_codemap); - - reader::tagged_docs(cm_doc, tag_codemap_filemap).map(|filemap_doc| { - Decodable::decode(&mut filemap_doc.decoder()).unwrap() - }).collect() + rbml::Doc::new(metadata).get(tag_codemap).decoder().decode() } pub fn closure_kind(cdata: Cmd, closure_id: DefIndex) -> ty::ClosureKind { - let closure_doc = cdata.lookup_item(closure_id); - let closure_kind_doc = reader::get_doc(closure_doc, tag_items_closure_kind); - ty::ClosureKind::decode(&mut closure_kind_doc.decoder()).unwrap() + cdata.lookup_item(closure_id).get(tag_items_closure_kind).decoder().decode() } pub fn closure_ty<'a, 'tcx>(cdata: Cmd, closure_id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ty::ClosureTy<'tcx> { let closure_doc = cdata.lookup_item(closure_id); - let closure_ty_doc = reader::get_doc(closure_doc, tag_items_closure_ty); + let closure_ty_doc = closure_doc.get(tag_items_closure_ty); let mut dcx = closure_ty_doc.decoder(); dcx.tcx = Some(tcx); dcx.cdata = Some(cdata); - Decodable::decode(&mut dcx).unwrap() + dcx.decode() } pub fn def_key(cdata: Cmd, id: DefIndex) -> hir_map::DefKey { @@ -1726,10 +1327,8 @@ pub fn def_key(cdata: Cmd, id: DefIndex) -> hir_map::DefKey { fn item_def_key(item_doc: rbml::Doc) -> hir_map::DefKey { match reader::maybe_get_doc(item_doc, tag_def_key) { Some(def_key_doc) => { - let simple_key = def_key::DefKey::decode(&mut def_key_doc.decoder()).unwrap(); - let name = reader::maybe_get_doc(item_doc, tag_paths_data_name).map(|name| { - token::intern(name.as_str()).as_str() - }); + let simple_key = def_key_doc.decoder().decode(); + let name = maybe_item_name(item_doc).map(|name| name.as_str()); def_key::recover_def_key(simple_key, name) } None => { @@ -1753,11 +1352,5 @@ pub fn def_path(cdata: Cmd, id: DefIndex) -> Option { } pub fn get_panic_strategy(data: &[u8]) -> PanicStrategy { - let crate_doc = rbml::Doc::new(data); - let strat_doc = reader::get_doc(crate_doc, tag_panic_strategy); - match reader::doc_as_u8(strat_doc) { - b'U' => PanicStrategy::Unwind, - b'A' => PanicStrategy::Abort, - b => panic!("unknown panic strategy in metadata: {}", b), - } + rbml::Doc::new(data).get(tag_panic_strategy).decoder().decode() } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index e414275f8b425..7b4a6972d221b 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -20,7 +20,7 @@ use decoder; use def_key; use index::{self, IndexData}; -use middle::cstore::{InlinedItemRef, LinkMeta}; +use middle::cstore::{InlinedItemRef, LinkMeta, LinkagePreference}; use rustc::hir::def; use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId}; use middle::dependency_format::Linkage; @@ -28,24 +28,22 @@ use rustc::dep_graph::DepNode; use rustc::traits::specialization_graph; use rustc::ty::{self, Ty, TyCtxt}; -use rustc::hir::svh::Svh; use rustc::mir::mir_map::MirMap; -use rustc::session::config::{self, PanicStrategy, CrateTypeRustcMacro}; +use rustc::session::config::{self, CrateTypeRustcMacro}; use rustc::util::nodemap::{FnvHashMap, NodeSet}; use rustc_serialize::{Encodable, Encoder, SpecializedEncoder, opaque}; -use rustc_serialize as serialize; use std::cell::RefCell; use std::intrinsics; use std::io::prelude::*; use std::io::Cursor; +use std::mem; use std::ops::{Deref, DerefMut}; use std::rc::Rc; use std::u32; use syntax::ast::{self, NodeId, Name, CRATE_NODE_ID}; use syntax::attr; use syntax; -use syntax_pos::BytePos; use rbml; use rustc::hir::{self, PatKind}; @@ -53,7 +51,7 @@ use rustc::hir::intravisit::Visitor; use rustc::hir::intravisit; use rustc::hir::map::DefKey; -use super::index_builder::{FromId, IndexBuilder, ItemContentBuilder, Untracked, XRef}; +use super::index_builder::{FromId, IndexBuilder, Untracked}; pub struct EncodeContext<'a, 'tcx: 'a> { rbml_w: rbml::writer::Encoder<'a>, @@ -61,11 +59,17 @@ pub struct EncodeContext<'a, 'tcx: 'a> { reexports: &'a def::ExportMap, link_meta: &'a LinkMeta, cstore: &'a cstore::CStore, - type_shorthands: RefCell, usize>>, reachable: &'a NodeSet, mir_map: &'a MirMap<'tcx>, + + type_shorthands: RefCell, usize>>, + xrefs: FnvHashMap, u32>, // sequentially-assigned } +/// "interned" entries referenced by id +#[derive(PartialEq, Eq, Hash)] +enum XRef<'tcx> { Predicate(ty::Predicate<'tcx>) } + impl<'a, 'tcx> Deref for EncodeContext<'a, 'tcx> { type Target = rbml::writer::Encoder<'a>; fn deref(&self) -> &Self::Target { @@ -87,8 +91,8 @@ macro_rules! encoder_methods { } } -impl<'a, 'tcx> serialize::Encoder for ::encoder::EncodeContext<'a, 'tcx> { - type Error = as serialize::Encoder>::Error; +impl<'a, 'tcx> Encoder for EncodeContext<'a, 'tcx> { + type Error = as Encoder>::Error; fn emit_nil(&mut self) -> Result<(), Self::Error> { Ok(()) @@ -146,12 +150,35 @@ impl<'a, 'tcx> SpecializedEncoder> for EncodeContext<'a, 'tcx> { } } +impl<'a, 'tcx> EncodeContext<'a, 'tcx> { + fn seq(&mut self, iter: I, mut f: F) + where I: IntoIterator, + I::IntoIter: ExactSizeIterator, + F: FnMut(&mut Self, I::Item) -> T, + T: Encodable { + let iter = iter.into_iter(); + self.emit_seq(iter.len(), move |ecx| { + for (i, elem) in iter.enumerate() { + ecx.emit_seq_elt(i, |ecx| { + f(ecx, elem).encode(ecx) + })?; + } + Ok(()) + }).unwrap(); + } +} + fn encode_name(ecx: &mut EncodeContext, name: Name) { - ecx.wr_tagged_str(tag_paths_data_name, &name.as_str()); + ecx.start_tag(tag_paths_data_name); + name.encode(ecx).unwrap(); + ecx.end_tag(); } -fn encode_def_id(ecx: &mut EncodeContext, id: DefId) { - ecx.wr_tagged_u64(tag_def_id, def_to_u64(id)); +fn encode_def_id(ecx: &mut EncodeContext, def_id: DefId) { + assert!(def_id.is_local()); + ecx.start_tag(tag_def_index); + def_id.index.encode(ecx).unwrap(); + ecx.end_tag(); } fn encode_def_key(ecx: &mut EncodeContext, key: DefKey) { @@ -178,16 +205,10 @@ fn encode_trait_ref<'a, 'tcx>(ecx: &mut EncodeContext<'a, 'tcx>, } // Item info table encoding -fn encode_family(ecx: &mut EncodeContext, c: char) { - ecx.wr_tagged_u8(tag_items_data_item_family, c as u8); -} - -pub fn def_to_u64(did: DefId) -> u64 { - (did.krate.as_u32() as u64) << 32 | (did.index.as_u32() as u64) -} - -pub fn def_to_string(_tcx: TyCtxt, did: DefId) -> String { - format!("{}:{}", did.krate, did.index.as_usize()) +fn encode_family(ecx: &mut EncodeContext, f: Family) { + ecx.start_tag(tag_items_data_item_family); + f.encode(ecx).unwrap(); + ecx.end_tag(); } fn encode_item_variances(ecx: &mut EncodeContext, id: NodeId) { @@ -197,7 +218,7 @@ fn encode_item_variances(ecx: &mut EncodeContext, id: NodeId) { ecx.end_tag(); } -impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { +impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn encode_bounds_and_type_for_item(&mut self, def_id: DefId) { let tcx = self.tcx; self.encode_bounds_and_type(&tcx.lookup_item_type(def_id), @@ -210,44 +231,31 @@ impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { self.encode_generics(&scheme.generics, &predicates); self.encode_type(scheme.ty); } -} - -fn encode_variant_id(ecx: &mut EncodeContext, vid: DefId) { - let id = def_to_u64(vid); - ecx.wr_tagged_u64(tag_items_data_item_variant, id); - ecx.wr_tagged_u64(tag_mod_child, id); -} -impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { fn encode_type(&mut self, typ: Ty<'tcx>) { self.start_tag(tag_items_data_item_type); - typ.encode(self.ecx).unwrap(); + typ.encode(self).unwrap(); self.end_tag(); } fn encode_disr_val(&mut self, disr_val: ty::Disr) { - // convert to u64 so just the number is printed, without any type info - self.wr_tagged_str(tag_disr_val, &disr_val.to_u64_unchecked().to_string()); + self.start_tag(tag_disr_val); + disr_val.to_u64_unchecked().encode(self).unwrap(); + self.end_tag(); } fn encode_parent_item(&mut self, id: DefId) { - self.wr_tagged_u64(tag_items_data_parent_item, def_to_u64(id)); + self.start_tag(tag_items_data_parent_item); + id.encode(self).unwrap(); + self.end_tag(); } - fn encode_struct_fields(&mut self, - variant: ty::VariantDef) { - for f in &variant.fields { - if variant.kind == ty::VariantKind::Tuple { - self.start_tag(tag_item_unnamed_field); - } else { - self.start_tag(tag_item_field); - encode_name(self, f.name); - } - self.encode_struct_field_family(f.vis); - encode_def_id(self, f.did); - self.end_tag(); - } + fn encode_variant_fields(&mut self, + variant: ty::VariantDef) { + self.start_tag(tag_item_fields); + self.seq(&variant.fields, |_, f| f.did); + self.end_tag(); } } @@ -258,13 +266,13 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { self.encode_fields(enum_did); for (i, variant) in def.variants.iter().enumerate() { self.record(variant.did, - ItemContentBuilder::encode_enum_variant_info, + EncodeContext::encode_enum_variant_info, (enum_did, Untracked(i))); } } } -impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { +impl<'a, 'tcx> EncodeContext<'a, 'tcx> { /// Encode data for the given variant of the given ADT. The /// index of the variant is untracked: this is ok because we /// will have to lookup the adt-def by its id, and that gives us @@ -278,11 +286,7 @@ impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { let variant = &def.variants[index]; let vid = variant.did; encode_def_id_and_key(self, vid); - encode_family(self, match variant.kind { - ty::VariantKind::Struct => 'V', - ty::VariantKind::Tuple => 'v', - ty::VariantKind::Unit => 'w', - }); + encode_family(self, Family::Variant(variant.kind)); encode_name(self, variant.name); self.encode_parent_item(enum_did); @@ -299,51 +303,35 @@ impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { encode_stability(self, stab); encode_deprecation(self, depr); - self.encode_struct_fields(variant); + self.encode_variant_fields(variant); self.encode_disr_val(variant.disr_val); self.encode_bounds_and_type_for_item(vid); } } -fn encode_reexports(ecx: &mut EncodeContext, id: NodeId) { - debug!("(encoding info for module) encoding reexports for {}", id); - match ecx.reexports.get(&id) { - Some(exports) => { - debug!("(encoding info for module) found reexports for {}", id); - for exp in exports { - debug!("(encoding info for module) reexport '{}' ({:?}) for \ - {}", - exp.name, - exp.def_id, - id); - ecx.start_tag(tag_items_data_item_reexport); - ecx.wr_tagged_u64(tag_items_data_item_reexport_def_id, - def_to_u64(exp.def_id)); - ecx.wr_tagged_str(tag_items_data_item_reexport_name, - &exp.name.as_str()); - ecx.end_tag(); - } - }, - None => debug!("(encoding info for module) found no reexports for {}", id), - } -} - -impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { +impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn encode_info_for_mod(&mut self, FromId(id, (md, attrs, name, vis)): FromId<(&hir::Mod, &[ast::Attribute], Name, &hir::Visibility)>) { let tcx = self.tcx; encode_def_id_and_key(self, tcx.map.local_def_id(id)); - encode_family(self, 'm'); + encode_family(self, Family::Mod); encode_name(self, name); debug!("(encoding info for module) encoding info for module ID {}", id); // Encode info about all the module children. - for item_id in &md.item_ids { - self.wr_tagged_u64(tag_mod_child, - def_to_u64(tcx.map.local_def_id(item_id.id))); + self.start_tag(tag_mod_children); + self.seq(&md.item_ids, |_, item_id| { + tcx.map.local_def_id(item_id.id) + }); + + // Encode the reexports of this module, if this module is public. + match self.reexports.get(&id) { + Some(exports) if *vis == hir::Public => exports.encode(self).unwrap(), + _ => <[def::Export]>::encode(&[], self).unwrap() } + self.end_tag(); self.encode_visibility(vis); @@ -352,22 +340,27 @@ impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { encode_stability(self, stab); encode_deprecation(self, depr); - // Encode the reexports of this module, if this module is public. - if *vis == hir::Public { - debug!("(encoding info for module) encoding reexports for {}", id); - encode_reexports(self, id); - } encode_attributes(self, attrs); } fn encode_struct_field_family(&mut self, visibility: ty::Visibility) { - encode_family(self, if visibility.is_public() { 'g' } else { 'N' }); + encode_family(self, if visibility.is_public() { + Family::PublicField + } else { + Family::InheritedField + }); } fn encode_visibility(&mut self, visibility: T) { - let ch = if visibility.is_public() { 'y' } else { 'i' }; - self.wr_tagged_u8(tag_items_data_item_visibility, ch as u8); + let vis = if visibility.is_public() { + ty::Visibility::Public + } else { + ty::Visibility::PrivateExternal + }; + self.start_tag(tag_items_data_item_visibility); + vis.encode(self).unwrap(); + self.end_tag(); } } @@ -389,54 +382,14 @@ impl HasVisibility for ty::Visibility { fn encode_constness(ecx: &mut EncodeContext, constness: hir::Constness) { ecx.start_tag(tag_items_data_item_constness); - let ch = match constness { - hir::Constness::Const => 'c', - hir::Constness::NotConst => 'n', - }; - ecx.wr_str(&ch.to_string()); + constness.encode(ecx).unwrap(); ecx.end_tag(); } fn encode_defaultness(ecx: &mut EncodeContext, defaultness: hir::Defaultness) { - let ch = match defaultness { - hir::Defaultness::Default => 'd', - hir::Defaultness::Final => 'f', - }; - ecx.wr_tagged_u8(tag_items_data_item_defaultness, ch as u8); -} - -fn encode_explicit_self(ecx: &mut EncodeContext, - explicit_self: &ty::ExplicitSelfCategory) { - let tag = tag_item_trait_method_explicit_self; - - // Encode the base self type. - match *explicit_self { - ty::ExplicitSelfCategory::Static => { - ecx.wr_tagged_bytes(tag, &['s' as u8]); - } - ty::ExplicitSelfCategory::ByValue => { - ecx.wr_tagged_bytes(tag, &['v' as u8]); - } - ty::ExplicitSelfCategory::ByBox => { - ecx.wr_tagged_bytes(tag, &['~' as u8]); - } - ty::ExplicitSelfCategory::ByReference(_, m) => { - // FIXME(#4846) encode custom lifetime - let ch = encode_mutability(m); - ecx.wr_tagged_bytes(tag, &['&' as u8, ch]); - } - } - - fn encode_mutability(m: hir::Mutability) -> u8 { - match m { - hir::MutImmutable => 'i' as u8, - hir::MutMutable => 'm' as u8, - } - } -} - -fn encode_item_sort(ecx: &mut EncodeContext, sort: char) { - ecx.wr_tagged_u8(tag_item_trait_item_sort, sort as u8); + ecx.start_tag(tag_items_data_item_defaultness); + defaultness.encode(ecx).unwrap(); + ecx.end_tag(); } impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { @@ -446,14 +399,14 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { for (variant_index, variant) in def.variants.iter().enumerate() { for (field_index, field) in variant.fields.iter().enumerate() { self.record(field.did, - ItemContentBuilder::encode_field, + EncodeContext::encode_field, (adt_def_id, Untracked((variant_index, field_index)))); } } } } -impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { +impl<'a, 'tcx> EncodeContext<'a, 'tcx> { /// Encode data for the given field of the given variant of the /// given ADT. The indices of the variant/field are untracked: /// this is ok because we will have to lookup the adt-def by its @@ -476,6 +429,10 @@ impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { self.encode_bounds_and_type_for_item(field.did); encode_def_id_and_key(self, field.did); + let variant_id = tcx.map.as_local_node_id(variant.did).unwrap(); + let variant_data = tcx.map.expect_variant_data(variant_id); + encode_attributes(self, &variant_data.fields()[field_index].attrs); + let stab = tcx.lookup_stability(field.did); let depr = tcx.lookup_deprecation(field.did); encode_stability(self, stab); @@ -491,11 +448,7 @@ impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { let item = tcx.map.expect_item(struct_node_id); let ctor_def_id = tcx.map.local_def_id(ctor_node_id); encode_def_id_and_key(self, ctor_def_id); - encode_family(self, match variant.kind { - ty::VariantKind::Struct => 'S', - ty::VariantKind::Tuple => 's', - ty::VariantKind::Unit => 'u', - }); + encode_family(self, Family::Struct(variant.kind)); self.encode_bounds_and_type_for_item(ctor_def_id); encode_name(self, item.name); self.encode_parent_item(struct_def_id); @@ -510,7 +463,9 @@ impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { // definition, but without this there is no way for them // to tell that they actually have a ctor rather than a // normal function - self.wr_tagged_bytes(tag_items_data_item_is_tuple_struct_ctor, &[]); + self.start_tag(tag_items_data_item_is_tuple_struct_ctor); + true.encode(self).unwrap(); + self.end_tag(); } fn encode_generics(&mut self, @@ -518,7 +473,7 @@ impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { predicates: &ty::GenericPredicates<'tcx>) { self.start_tag(tag_item_generics); - generics.encode(self.ecx).unwrap(); + generics.encode(self).unwrap(); self.end_tag(); self.encode_predicates(predicates, tag_item_predicates); } @@ -527,13 +482,10 @@ impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { predicates: &ty::GenericPredicates<'tcx>, tag: usize) { self.start_tag(tag); - if let Some(def_id) = predicates.parent { - self.wr_tagged_u64(tag_items_data_parent_item, def_to_u64(def_id)); - } - for predicate in &predicates.predicates { - let xref = self.add_xref(XRef::Predicate(predicate.clone())); - self.wr_tagged_u32(tag_predicate, xref); - } + predicates.parent.encode(self).unwrap(); + self.seq(&predicates.predicates, |ecx, predicate| { + ecx.add_xref(XRef::Predicate(predicate.clone())) + }); self.end_tag(); } @@ -542,13 +494,12 @@ impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { encode_name(self, method_ty.name); self.encode_generics(&method_ty.generics, &method_ty.predicates); self.encode_visibility(method_ty.vis); - encode_explicit_self(self, &method_ty.explicit_self); - match method_ty.explicit_self { - ty::ExplicitSelfCategory::Static => { - encode_family(self, STATIC_METHOD_FAMILY); - } - _ => encode_family(self, METHOD_FAMILY) - } + + self.start_tag(tag_item_trait_method_explicit_self); + method_ty.explicit_self.encode(self).unwrap(); + self.end_tag(); + + encode_family(self, Family::Method); } fn encode_info_for_trait_item(&mut self, @@ -563,79 +514,47 @@ impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { encode_stability(self, stab); encode_deprecation(self, depr); - let trait_item_type = - tcx.impl_or_trait_item(item_def_id); - let is_nonstatic_method; - match trait_item_type { + match tcx.impl_or_trait_item(item_def_id) { ty::ConstTraitItem(associated_const) => { encode_name(self, associated_const.name); - encode_def_id_and_key(self, associated_const.def_id); + encode_def_id_and_key(self, item_def_id); self.encode_visibility(associated_const.vis); - encode_family(self, 'C'); - - self.encode_bounds_and_type_for_item(associated_const.def_id); - - is_nonstatic_method = false; + encode_family(self, Family::AssociatedConst); + self.encode_bounds_and_type_for_item(item_def_id); } ty::MethodTraitItem(method_ty) => { - let method_def_id = item_def_id; - self.encode_method_ty_fields(&method_ty); - - match method_ty.explicit_self { - ty::ExplicitSelfCategory::Static => { - encode_family(self, STATIC_METHOD_FAMILY); - } - _ => { - encode_family(self, METHOD_FAMILY); - } - } - self.encode_bounds_and_type_for_item(method_def_id); - - is_nonstatic_method = method_ty.explicit_self != - ty::ExplicitSelfCategory::Static; + self.encode_bounds_and_type_for_item(item_def_id); } ty::TypeTraitItem(associated_type) => { encode_name(self, associated_type.name); - encode_def_id_and_key(self, associated_type.def_id); - encode_item_sort(self, 't'); - encode_family(self, 'y'); + encode_def_id_and_key(self, item_def_id); + encode_family(self, Family::AssociatedType); if let Some(ty) = associated_type.ty { self.encode_type(ty); } - - is_nonstatic_method = false; } } encode_attributes(self, &trait_item.attrs); match trait_item.node { hir::ConstTraitItem(_, ref default) => { - if default.is_some() { - encode_item_sort(self, 'C'); - } else { - encode_item_sort(self, 'c'); - } + self.start_tag(tag_item_trait_item_has_body); + default.is_some().encode(self).unwrap(); + self.end_tag(); encode_inlined_item(self, InlinedItemRef::TraitItem(trait_def_id, trait_item)); self.encode_mir(item_def_id); } hir::MethodTraitItem(ref sig, ref body) => { - // If this is a static method, we've already - // encoded self. - if is_nonstatic_method { - self.encode_bounds_and_type_for_item(item_def_id); - } + self.start_tag(tag_item_trait_item_has_body); + body.is_some().encode(self).unwrap(); + self.end_tag(); - if body.is_some() { - encode_item_sort(self, 'p'); - self.encode_mir(item_def_id); - } else { - encode_item_sort(self, 'r'); - } + self.encode_mir(item_def_id); self.encode_method_argument_names(&sig.decl); } @@ -654,7 +573,6 @@ impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { } ty::MethodTraitItem(ref method_type) => { self.encode_info_for_method(&method_type, - false, impl_id, ast_item) } @@ -678,10 +596,13 @@ impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { encode_def_id_and_key(self, associated_const.def_id); encode_name(self, associated_const.name); self.encode_visibility(associated_const.vis); - encode_family(self, 'C'); + encode_family(self, Family::AssociatedConst); self.encode_parent_item(tcx.map.local_def_id(parent_id)); - encode_item_sort(self, 'C'); + + self.start_tag(tag_item_trait_item_has_body); + true.encode(self).unwrap(); + self.end_tag(); self.encode_bounds_and_type_for_item(associated_const.def_id); @@ -702,7 +623,6 @@ impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { fn encode_info_for_method(&mut self, m: &ty::Method<'tcx>, - is_default_impl: bool, parent_id: NodeId, impl_item_opt: Option<&hir::ImplItem>) { let tcx = self.tcx; @@ -711,7 +631,10 @@ impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { m.name); self.encode_method_ty_fields(m); self.encode_parent_item(tcx.map.local_def_id(parent_id)); - encode_item_sort(self, 'r'); + + self.start_tag(tag_item_trait_item_has_body); + true.encode(self).unwrap(); + self.end_tag(); let stab = tcx.lookup_stability(m.def_id); let depr = tcx.lookup_deprecation(m.def_id); @@ -725,8 +648,7 @@ impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { encode_attributes(self, &impl_item.attrs); let generics = tcx.lookup_generics(m.def_id); let types = generics.parent_types as usize + generics.types.len(); - let needs_inline = types > 0 || is_default_impl || - attr::requests_inline(&impl_item.attrs); + let needs_inline = types > 0 || attr::requests_inline(&impl_item.attrs); if sig.constness == hir::Constness::Const { encode_inlined_item( self, @@ -755,9 +677,8 @@ impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { encode_def_id_and_key(self, associated_type.def_id); encode_name(self, associated_type.name); self.encode_visibility(associated_type.vis); - encode_family(self, 'y'); + encode_family(self, Family::AssociatedType); self.encode_parent_item(tcx.map.local_def_id(parent_id)); - encode_item_sort(self, 't'); let stab = tcx.lookup_stability(associated_type.def_id); let depr = tcx.lookup_deprecation(associated_type.def_id); @@ -777,15 +698,15 @@ impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { fn encode_method_argument_names(&mut self, decl: &hir::FnDecl) { self.start_tag(tag_method_argument_names); - for arg in &decl.inputs { - let tag = tag_method_argument_name; + + self.seq(&decl.inputs, |_, arg| { if let PatKind::Binding(_, ref path1, _) = arg.pat.node { - let name = path1.node.as_str(); - self.wr_tagged_bytes(tag, name.as_bytes()); + path1.node } else { - self.wr_tagged_bytes(tag, &[]); + syntax::parse::token::intern("") } - } + }); + self.end_tag(); } @@ -797,36 +718,28 @@ impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { attr)); } self.start_tag(tag_items_data_item_repr); - repr_attrs.encode(self.ecx); + repr_attrs.encode(self); self.end_tag(); } fn encode_mir(&mut self, def_id: DefId) { if let Some(mir) = self.mir_map.map.get(&def_id) { self.start_tag(tag_mir as usize); - mir.encode(self.ecx); + mir.encode(self); self.end_tag(); } } } -const FN_FAMILY: char = 'f'; -const STATIC_METHOD_FAMILY: char = 'F'; -const METHOD_FAMILY: char = 'h'; - // Encodes the inherent implementations of a structure, enumeration, or trait. fn encode_inherent_implementations(ecx: &mut EncodeContext, def_id: DefId) { + ecx.start_tag(tag_items_data_item_inherent_impls); match ecx.tcx.inherent_impls.borrow().get(&def_id) { - None => {} - Some(implementations) => { - for &impl_def_id in implementations.iter() { - ecx.start_tag(tag_items_data_item_inherent_impl); - encode_def_id(ecx, impl_def_id); - ecx.end_tag(); - } - } + None => <[DefId]>::encode(&[], ecx).unwrap(), + Some(implementations) => implementations.encode(ecx).unwrap() } + ecx.end_tag(); } fn encode_stability(ecx: &mut EncodeContext, stab_opt: Option<&attr::Stability>) { @@ -845,37 +758,35 @@ fn encode_deprecation(ecx: &mut EncodeContext, depr_opt: Option) { - parent_opt.map(|parent| { - ecx.wr_tagged_u64(tag_items_data_parent_impl, def_to_u64(parent)); - }); -} +impl<'a, 'tcx> EncodeContext<'a, 'tcx> { + fn add_xref(&mut self, xref: XRef<'tcx>) -> u32 { + let old_len = self.xrefs.len() as u32; + *self.xrefs.entry(xref).or_insert(old_len) + } -fn encode_xrefs<'a, 'tcx>(ecx: &mut EncodeContext<'a, 'tcx>, - xrefs: FnvHashMap, u32>) -{ - let mut xref_positions = vec![0; xrefs.len()]; + fn encode_xrefs(&mut self) { + let xrefs = mem::replace(&mut self.xrefs, Default::default()); + let mut xref_positions = vec![0; xrefs.len()]; - // Encode XRefs sorted by their ID - let mut sorted_xrefs: Vec<_> = xrefs.into_iter().collect(); - sorted_xrefs.sort_by_key(|&(_, id)| id); + // Encode XRefs sorted by their ID + let mut sorted_xrefs: Vec<_> = xrefs.into_iter().collect(); + sorted_xrefs.sort_by_key(|&(_, id)| id); - ecx.start_tag(tag_xref_data); - for (xref, id) in sorted_xrefs.into_iter() { - xref_positions[id as usize] = ecx.mark_stable_position() as u32; - match xref { - XRef::Predicate(p) => p.encode(ecx).unwrap() + self.start_tag(tag_xref_data); + for (xref, id) in sorted_xrefs.into_iter() { + xref_positions[id as usize] = self.mark_stable_position() as u32; + match xref { + XRef::Predicate(p) => p.encode(self).unwrap() + } } - } - ecx.mark_stable_position(); - ecx.end_tag(); + self.mark_stable_position(); + self.end_tag(); - ecx.start_tag(tag_xref_index); - index::write_dense_index(xref_positions, &mut ecx.opaque.cursor); - ecx.end_tag(); -} + self.start_tag(tag_xref_index); + index::write_dense_index(xref_positions, &mut self.opaque.cursor); + self.end_tag(); + } -impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { fn encode_info_for_item(&mut self, (def_id, item): (DefId, &hir::Item)) { let tcx = self.tcx; @@ -893,11 +804,11 @@ impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { match item.node { hir::ItemStatic(_, m, _) => { encode_def_id_and_key(self, def_id); - if m == hir::MutMutable { - encode_family(self, 'b'); + encode_family(self, if m == hir::MutMutable { + Family::MutStatic } else { - encode_family(self, 'c'); - } + Family::ImmStatic + }); self.encode_bounds_and_type_for_item(def_id); encode_name(self, item.name); self.encode_visibility(vis); @@ -907,7 +818,7 @@ impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { } hir::ItemConst(..) => { encode_def_id_and_key(self, def_id); - encode_family(self, 'C'); + encode_family(self, Family::Const); self.encode_bounds_and_type_for_item(def_id); encode_name(self, item.name); encode_attributes(self, &item.attrs); @@ -919,7 +830,7 @@ impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { } hir::ItemFn(ref decl, _, constness, _, ref generics, _) => { encode_def_id_and_key(self, def_id); - encode_family(self, FN_FAMILY); + encode_family(self, Family::Fn); let tps_len = generics.ty_params.len(); self.encode_bounds_and_type_for_item(def_id); encode_name(self, item.name); @@ -942,22 +853,24 @@ impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { } hir::ItemForeignMod(ref fm) => { encode_def_id_and_key(self, def_id); - encode_family(self, 'n'); + encode_family(self, Family::ForeignMod); encode_name(self, item.name); // Encode all the items in self module. - for foreign_item in &fm.items { - self.wr_tagged_u64( - tag_mod_child, - def_to_u64(tcx.map.local_def_id(foreign_item.id))); - } + self.start_tag(tag_mod_children); + self.seq(&fm.items, |_, foreign_item| { + tcx.map.local_def_id(foreign_item.id) + }); + <[def::Export]>::encode(&[], self).unwrap(); + self.end_tag(); + self.encode_visibility(vis); encode_stability(self, stab); encode_deprecation(self, depr); } hir::ItemTy(..) => { encode_def_id_and_key(self, def_id); - encode_family(self, 'y'); + encode_family(self, Family::Type); self.encode_bounds_and_type_for_item(def_id); encode_name(self, item.name); self.encode_visibility(vis); @@ -966,15 +879,19 @@ impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { } hir::ItemEnum(ref enum_definition, _) => { encode_def_id_and_key(self, def_id); - encode_family(self, 't'); + encode_family(self, Family::Enum); encode_item_variances(self, item.id); self.encode_bounds_and_type_for_item(def_id); encode_name(self, item.name); encode_attributes(self, &item.attrs); self.encode_repr_attrs(&item.attrs); - for v in &enum_definition.variants { - encode_variant_id(self, tcx.map.local_def_id(v.node.data.id())); - } + + self.start_tag(tag_mod_children); + self.seq(&enum_definition.variants, |_, v| { + tcx.map.local_def_id(v.node.data.id()) + }); + <[def::Export]>::encode(&[], self).unwrap(); + self.end_tag(); // Encode inherent implementations for self enumeration. encode_inherent_implementations(self, def_id); @@ -990,11 +907,7 @@ impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { /* Now, make an item for the class itself */ encode_def_id_and_key(self, def_id); - encode_family(self, match *struct_def { - hir::VariantData::Struct(..) => 'S', - hir::VariantData::Tuple(..) => 's', - hir::VariantData::Unit(..) => 'u', - }); + encode_family(self, Family::Struct(variant.kind)); self.encode_bounds_and_type_for_item(def_id); encode_item_variances(self, item.id); @@ -1008,15 +921,16 @@ impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { /* Encode def_ids for each field and method for methods, write all the stuff get_trait_method needs to know*/ - self.encode_struct_fields(variant); + self.encode_variant_fields(variant); // Encode inherent implementations for self structure. encode_inherent_implementations(self, def_id); if !struct_def.is_struct() { let ctor_did = tcx.map.local_def_id(struct_def.id()); - self.wr_tagged_u64(tag_items_data_item_struct_ctor, - def_to_u64(ctor_did)); + self.start_tag(tag_items_data_item_struct_ctor); + ctor_did.encode(self).unwrap(); + self.end_tag(); } } hir::ItemUnion(..) => { @@ -1024,7 +938,7 @@ impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { let variant = def.struct_variant(); encode_def_id_and_key(self, def_id); - encode_family(self, 'U'); + encode_family(self, Family::Union); self.encode_bounds_and_type_for_item(def_id); encode_item_variances(self, item.id); @@ -1038,7 +952,7 @@ impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { /* Encode def_ids for each field and method for methods, write all the stuff get_trait_method needs to know*/ - self.encode_struct_fields(variant); + self.encode_variant_fields(variant); encode_inlined_item(self, InlinedItemRef::Item(def_id, item)); self.encode_mir(def_id); @@ -1046,28 +960,24 @@ impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { // Encode inherent implementations for self union. encode_inherent_implementations(self, def_id); } - hir::ItemDefaultImpl(unsafety, _) => { + hir::ItemDefaultImpl(..) => { encode_def_id_and_key(self, def_id); - encode_family(self, 'd'); + encode_family(self, Family::DefaultImpl); encode_name(self, item.name); - encode_unsafety(self, unsafety); let trait_ref = tcx.impl_trait_ref(tcx.map.local_def_id(item.id)).unwrap(); encode_trait_ref(self, trait_ref, tag_item_trait_ref); } - hir::ItemImpl(unsafety, polarity, ..) => { - // We need to encode information about the default methods we - // have inherited, so we drive self based on the impl structure. - let impl_items = tcx.impl_items.borrow(); - let items = &impl_items[&def_id]; - + hir::ItemImpl(_, polarity, ..) => { encode_def_id_and_key(self, def_id); - encode_family(self, 'i'); + encode_family(self, Family::Impl); self.encode_bounds_and_type_for_item(def_id); encode_name(self, item.name); encode_attributes(self, &item.attrs); - encode_unsafety(self, unsafety); - encode_polarity(self, polarity); + + self.start_tag(tag_polarity); + polarity.encode(self).unwrap(); + self.end_tag(); match tcx.custom_coerce_unsized_kinds @@ -1076,30 +986,17 @@ impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { { Some(&kind) => { self.start_tag(tag_impl_coerce_unsized_kind); - kind.encode(self.ecx); + kind.encode(self); self.end_tag(); } None => {} } - for &item_def_id in items { - self.start_tag(tag_item_impl_item); - match item_def_id { - ty::ConstTraitItemId(item_def_id) => { - encode_def_id(self, item_def_id); - encode_item_sort(self, 'C'); - } - ty::MethodTraitItemId(item_def_id) => { - encode_def_id(self, item_def_id); - encode_item_sort(self, 'r'); - } - ty::TypeTraitItemId(item_def_id) => { - encode_def_id(self, item_def_id); - encode_item_sort(self, 't'); - } - } - self.end_tag(); - } + self.start_tag(tag_mod_children); + let items = tcx.impl_or_trait_items(def_id); + self.seq(&items[..], |_, id| id.def_id()); + <[def::Export]>::encode(&[], self).unwrap(); + self.end_tag(); let did = tcx.map.local_def_id(item.id); if let Some(trait_ref) = tcx.impl_trait_ref(did) { @@ -1114,20 +1011,34 @@ impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { Some(parent), _ => None, }); - encode_parent_impl(self, parent); + parent.map(|parent| { + self.start_tag(tag_items_data_parent_impl); + parent.encode(self).unwrap(); + self.end_tag(); + }); } encode_stability(self, stab); encode_deprecation(self, depr); } hir::ItemTrait(..) => { encode_def_id_and_key(self, def_id); - encode_family(self, 'I'); + encode_family(self, Family::Trait); encode_item_variances(self, item.id); let trait_def = tcx.lookup_trait_def(def_id); let trait_predicates = tcx.lookup_predicates(def_id); - encode_unsafety(self, trait_def.unsafety); - encode_paren_sugar(self, trait_def.paren_sugar); - encode_defaulted(self, tcx.trait_has_default_impl(def_id)); + + self.start_tag(tag_unsafety); + trait_def.unsafety.encode(self).unwrap(); + self.end_tag(); + + self.start_tag(tag_paren_sugar); + trait_def.paren_sugar.encode(self).unwrap(); + self.end_tag(); + + self.start_tag(tag_defaulted_trait); + tcx.trait_has_default_impl(def_id).encode(self).unwrap(); + self.end_tag(); + encode_associated_type_names(self, &trait_def.associated_type_names); self.encode_generics(&trait_def.generics, &trait_predicates); self.encode_predicates(&tcx.lookup_super_predicates(def_id), @@ -1138,27 +1049,12 @@ impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { self.encode_visibility(vis); encode_stability(self, stab); encode_deprecation(self, depr); - for &method_def_id in tcx.trait_item_def_ids(def_id).iter() { - self.start_tag(tag_item_trait_item); - match method_def_id { - ty::ConstTraitItemId(const_def_id) => { - encode_def_id(self, const_def_id); - encode_item_sort(self, 'C'); - } - ty::MethodTraitItemId(method_def_id) => { - encode_def_id(self, method_def_id); - encode_item_sort(self, 'r'); - } - ty::TypeTraitItemId(type_def_id) => { - encode_def_id(self, type_def_id); - encode_item_sort(self, 't'); - } - } - self.end_tag(); - self.wr_tagged_u64(tag_mod_child, - def_to_u64(method_def_id.def_id())); - } + self.start_tag(tag_mod_children); + let items = tcx.impl_or_trait_items(def_id); + self.seq(&items[..], |_, id| id.def_id()); + <[def::Export]>::encode(&[], self).unwrap(); + self.end_tag(); // Encode inherent implementations for self trait. encode_inherent_implementations(self, def_id); @@ -1227,7 +1123,7 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { // Foo()` and `struct Foo` let ctor_def_id = self.tcx.map.local_def_id(struct_node_id); self.record(ctor_def_id, - ItemContentBuilder::encode_struct_ctor, + EncodeContext::encode_struct_ctor, (def_id, item.id, struct_node_id)); } } @@ -1241,8 +1137,7 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { def_id: DefId, impl_id: ast::NodeId, ast_items: &[hir::ImplItem]) { - let impl_items = self.tcx.impl_items.borrow(); - let items = &impl_items[&def_id]; + let items = self.tcx.impl_or_trait_items(def_id); // Iterate down the trait items, emitting them. We rely on the // assumption that all of the actually implemented trait items @@ -1258,7 +1153,7 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { let trait_item_def_id = trait_item_def_id.def_id(); self.record(trait_item_def_id, - ItemContentBuilder::encode_info_for_impl_item, + EncodeContext::encode_info_for_impl_item, (impl_id, trait_item_def_id, ast_item)); } } @@ -1267,19 +1162,18 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { def_id: DefId, trait_items: &[hir::TraitItem]) { // Now output the trait item info for each trait item. - let tcx = self.tcx; - let r = tcx.trait_item_def_ids(def_id); + let r = self.tcx.impl_or_trait_items(def_id); for (item_def_id, trait_item) in r.iter().zip(trait_items) { let item_def_id = item_def_id.def_id(); assert!(item_def_id.is_local()); self.record(item_def_id, - ItemContentBuilder::encode_info_for_trait_item, + EncodeContext::encode_info_for_trait_item, (def_id, item_def_id, trait_item)); } } } -impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { +impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn encode_info_for_foreign_item(&mut self, (def_id, nitem): (DefId, &hir::ForeignItem)) { let tcx = self.tcx; @@ -1292,7 +1186,7 @@ impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { self.encode_visibility(&nitem.vis); match nitem.node { hir::ForeignItemFn(ref fndecl, _) => { - encode_family(self, FN_FAMILY); + encode_family(self, Family::Fn); self.encode_bounds_and_type_for_item(def_id); encode_name(self, nitem.name); encode_attributes(self, &nitem.attrs); @@ -1303,11 +1197,11 @@ impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { self.encode_method_argument_names(&fndecl); } hir::ForeignItemStatic(_, mutbl) => { - if mutbl { - encode_family(self, 'b'); + encode_family(self, if mutbl { + Family::MutStatic } else { - encode_family(self, 'c'); - } + Family::ImmStatic + }); self.encode_bounds_and_type_for_item(def_id); encode_attributes(self, &nitem.attrs); let stab = tcx.lookup_stability(tcx.map.local_def_id(nitem.id)); @@ -1335,7 +1229,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for EncodeVisitor<'a, 'b, 'tcx> { match item.node { hir::ItemExternCrate(_) | hir::ItemUse(_) => (), // ignore these _ => self.index.record(def_id, - ItemContentBuilder::encode_info_for_item, + EncodeContext::encode_info_for_item, (def_id, item)), } self.index.encode_addl_info_for_item(item); @@ -1344,7 +1238,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for EncodeVisitor<'a, 'b, 'tcx> { intravisit::walk_foreign_item(self, ni); let def_id = self.index.tcx.map.local_def_id(ni.id); self.index.record(def_id, - ItemContentBuilder::encode_info_for_foreign_item, + EncodeContext::encode_info_for_foreign_item, (def_id, ni)); } fn visit_ty(&mut self, ty: &'tcx hir::Ty) { @@ -1358,7 +1252,7 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { if let hir::TyImplTrait(_) = ty.node { let def_id = self.tcx.map.local_def_id(ty.id); self.record(def_id, - ItemContentBuilder::encode_info_for_anon_ty, + EncodeContext::encode_info_for_anon_ty, def_id); } } @@ -1368,7 +1262,7 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { hir::ExprClosure(..) => { let def_id = self.tcx.map.local_def_id(expr.id); self.record(def_id, - ItemContentBuilder::encode_info_for_closure, + EncodeContext::encode_info_for_closure, def_id); } _ => { } @@ -1376,10 +1270,9 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { } } -impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { +impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn encode_info_for_anon_ty(&mut self, def_id: DefId) { encode_def_id_and_key(self, def_id); - encode_family(self, 'y'); self.encode_bounds_and_type_for_item(def_id); } @@ -1389,11 +1282,11 @@ impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { encode_name(self, syntax::parse::token::intern("")); self.start_tag(tag_items_closure_ty); - tcx.tables.borrow().closure_tys[&def_id].encode(self.ecx).unwrap(); + tcx.tables.borrow().closure_tys[&def_id].encode(self).unwrap(); self.end_tag(); self.start_tag(tag_items_closure_kind); - tcx.closure_kind(def_id).encode(self.ecx).unwrap(); + tcx.closure_kind(def_id).encode(self).unwrap(); self.end_tag(); assert!(self.mir_map.map.contains_key(&def_id)); @@ -1401,30 +1294,29 @@ impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { } } -fn encode_info_for_items<'a, 'tcx>(ecx: &mut EncodeContext<'a, 'tcx>) - -> (IndexData, FnvHashMap, u32>) { +fn encode_info_for_items(ecx: &mut EncodeContext) -> IndexData { let krate = ecx.tcx.map.krate(); ecx.start_tag(tag_items_data); - let fields = { + let items = { let mut index = IndexBuilder::new(ecx); index.record(DefId::local(CRATE_DEF_INDEX), - ItemContentBuilder::encode_info_for_mod, + EncodeContext::encode_info_for_mod, FromId(CRATE_NODE_ID, (&krate.module, - &[], + &krate.attrs, syntax::parse::token::intern(&ecx.link_meta.crate_name), &hir::Public))); let mut visitor = EncodeVisitor { index: index, }; krate.visit_all_items(&mut visitor); - visitor.index.into_fields() + visitor.index.into_items() }; ecx.end_tag(); - fields + items } fn encode_item_index(ecx: &mut EncodeContext, index: IndexData) { @@ -1439,40 +1331,12 @@ fn encode_attributes(ecx: &mut EncodeContext, attrs: &[ast::Attribute]) { ecx.end_tag(); } -fn encode_unsafety(ecx: &mut EncodeContext, unsafety: hir::Unsafety) { - let byte: u8 = match unsafety { - hir::Unsafety::Normal => 0, - hir::Unsafety::Unsafe => 1, - }; - ecx.wr_tagged_u8(tag_unsafety, byte); -} - -fn encode_paren_sugar(ecx: &mut EncodeContext, paren_sugar: bool) { - let byte: u8 = if paren_sugar {1} else {0}; - ecx.wr_tagged_u8(tag_paren_sugar, byte); -} - -fn encode_defaulted(ecx: &mut EncodeContext, is_defaulted: bool) { - let byte: u8 = if is_defaulted {1} else {0}; - ecx.wr_tagged_u8(tag_defaulted_trait, byte); -} - fn encode_associated_type_names(ecx: &mut EncodeContext, names: &[Name]) { ecx.start_tag(tag_associated_type_names); - for &name in names { - ecx.wr_tagged_str(tag_associated_type_name, &name.as_str()); - } + names.encode(ecx).unwrap(); ecx.end_tag(); } -fn encode_polarity(ecx: &mut EncodeContext, polarity: hir::ImplPolarity) { - let byte: u8 = match polarity { - hir::ImplPolarity::Positive => 0, - hir::ImplPolarity::Negative => 1, - }; - ecx.wr_tagged_u8(tag_polarity, byte); -} - fn encode_crate_deps(ecx: &mut EncodeContext, cstore: &cstore::CStore) { fn get_ordered_deps(cstore: &cstore::CStore) -> Vec<(CrateNum, Rc)> { @@ -1500,48 +1364,56 @@ fn encode_crate_deps(ecx: &mut EncodeContext, cstore: &cstore::CStore) { // FIXME (#2166): This is not nearly enough to support correct versioning // but is enough to get transitive crate dependencies working. ecx.start_tag(tag_crate_deps); - for (_cnum, dep) in get_ordered_deps(cstore) { - encode_crate_dep(ecx, &dep); - } + ecx.seq(&get_ordered_deps(cstore), |_, &(_, ref dep)| { + (dep.name(), decoder::get_crate_hash(dep.data()), + dep.explicitly_linked.get()) + }); ecx.end_tag(); } fn encode_lang_items(ecx: &mut EncodeContext) { - ecx.start_tag(tag_lang_items); - - for (i, &opt_def_id) in ecx.tcx.lang_items.items().iter().enumerate() { - if let Some(def_id) = opt_def_id { - if def_id.is_local() { - ecx.start_tag(tag_lang_items_item); - ecx.wr_tagged_u32(tag_lang_items_item_id, i as u32); - ecx.wr_tagged_u32(tag_lang_items_item_index, def_id.index.as_u32()); - ecx.end_tag(); + let tcx = ecx.tcx; + let lang_items = || { + tcx.lang_items.items().iter().enumerate().filter_map(|(i, &opt_def_id)| { + if let Some(def_id) = opt_def_id { + if def_id.is_local() { + return Some((def_id.index, i)); + } } - } - } + None + }) + }; - for i in &ecx.tcx.lang_items.missing { - ecx.wr_tagged_u32(tag_lang_items_missing, *i as u32); - } + let count = lang_items().count(); + let mut lang_items = lang_items(); - ecx.end_tag(); // tag_lang_items + ecx.start_tag(tag_lang_items); + ecx.seq(0..count, |_, _| lang_items.next().unwrap()); + ecx.end_tag(); + + ecx.start_tag(tag_lang_items_missing); + tcx.lang_items.missing.encode(ecx).unwrap(); + ecx.end_tag(); } fn encode_native_libraries(ecx: &mut EncodeContext) { - ecx.start_tag(tag_native_libraries); - - for &(ref lib, kind) in ecx.tcx.sess.cstore.used_libraries().iter() { - match kind { - cstore::NativeStatic => {} // these libraries are not propagated - cstore::NativeFramework | cstore::NativeUnknown => { - ecx.start_tag(tag_native_libraries_lib); - ecx.wr_tagged_u32(tag_native_libraries_kind, kind as u32); - ecx.wr_tagged_str(tag_native_libraries_name, lib); - ecx.end_tag(); + let used_libraries = ecx.tcx.sess.cstore.used_libraries(); + let libs = || { + used_libraries.iter().filter_map(|&(ref lib, kind)| { + match kind { + cstore::NativeStatic => None, // these libraries are not propagated + cstore::NativeFramework | cstore::NativeUnknown => { + Some((kind, lib)) + } } - } - } + }) + }; + + let count = libs().count(); + let mut libs = libs(); + ecx.start_tag(tag_native_libraries); + ecx.seq(0..count, |_, _| libs.next().unwrap()); ecx.end_tag(); } @@ -1549,84 +1421,55 @@ fn encode_plugin_registrar_fn(ecx: &mut EncodeContext) { match ecx.tcx.sess.plugin_registrar_fn.get() { Some(id) => { let def_id = ecx.tcx.map.local_def_id(id); - ecx.wr_tagged_u32(tag_plugin_registrar_fn, def_id.index.as_u32()); + ecx.start_tag(tag_plugin_registrar_fn); + def_id.index.encode(ecx).unwrap(); + ecx.end_tag(); } None => {} } } fn encode_codemap(ecx: &mut EncodeContext) { - ecx.start_tag(tag_codemap); let codemap = ecx.tcx.sess.codemap(); + let all_filemaps = codemap.files.borrow(); + let filemaps = || { + // No need to export empty filemaps, as they can't contain spans + // that need translation. + // Also no need to re-export imported filemaps, as any downstream + // crate will import them from their original source. + all_filemaps.iter().filter(|filemap| { + !filemap.lines.borrow().is_empty() && !filemap.is_imported() + }) + }; - for filemap in &codemap.files.borrow()[..] { - - if filemap.lines.borrow().is_empty() || filemap.is_imported() { - // No need to export empty filemaps, as they can't contain spans - // that need translation. - // Also no need to re-export imported filemaps, as any downstream - // crate will import them from their original source. - continue; - } - - ecx.start_tag(tag_codemap_filemap); - filemap.encode(ecx).unwrap(); - ecx.end_tag(); - } + let count = filemaps().count(); + let mut filemaps = filemaps(); + ecx.start_tag(tag_codemap); + ecx.seq(0..count, |_, _| filemaps.next().unwrap()); ecx.end_tag(); } /// Serialize the text of the exported macros -fn encode_macro_defs(ecx: &mut EncodeContext, - krate: &hir::Crate) { +fn encode_macro_defs(ecx: &mut EncodeContext) { + let tcx = ecx.tcx; ecx.start_tag(tag_macro_defs); - for def in &krate.exported_macros { - ecx.start_tag(tag_macro_def); - - encode_name(ecx, def.name); - encode_attributes(ecx, &def.attrs); - let &BytePos(lo) = &def.span.lo; - let &BytePos(hi) = &def.span.hi; - ecx.wr_tagged_u32(tag_macro_def_span_lo, lo); - ecx.wr_tagged_u32(tag_macro_def_span_hi, hi); - - ecx.wr_tagged_str(tag_macro_def_body, - &::syntax::print::pprust::tts_to_string(&def.body)); - - ecx.end_tag(); - } + ecx.seq(&tcx.map.krate().exported_macros, |_, def| { + let body = ::syntax::print::pprust::tts_to_string(&def.body); + (def.name, &def.attrs, def.span, body) + }); ecx.end_tag(); if ecx.tcx.sess.crate_types.borrow().contains(&CrateTypeRustcMacro) { let id = ecx.tcx.sess.derive_registrar_fn.get().unwrap(); let did = ecx.tcx.map.local_def_id(id); - ecx.wr_tagged_u32(tag_macro_derive_registrar, did.index.as_u32()); - } -} -fn encode_struct_field_attrs(ecx: &mut EncodeContext, krate: &hir::Crate) { - struct StructFieldVisitor<'a, 'b:'a, 'tcx:'b> { - ecx: &'a mut EncodeContext<'b, 'tcx> - } - - impl<'a, 'b, 'tcx, 'v> Visitor<'v> for StructFieldVisitor<'a, 'b, 'tcx> { - fn visit_struct_field(&mut self, field: &hir::StructField) { - self.ecx.start_tag(tag_struct_field); - let def_id = self.ecx.tcx.map.local_def_id(field.id); - encode_def_id(self.ecx, def_id); - encode_attributes(self.ecx, &field.attrs); - self.ecx.end_tag(); - } + ecx.start_tag(tag_macro_derive_registrar); + did.index.encode(ecx).unwrap(); + ecx.end_tag(); } - - ecx.start_tag(tag_struct_fields); - krate.visit_all_items(&mut StructFieldVisitor { ecx: ecx }); - ecx.end_tag(); } - - struct ImplVisitor<'a, 'tcx:'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, impls: FnvHashMap> @@ -1646,20 +1489,19 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ImplVisitor<'a, 'tcx> { } /// Encodes an index, mapping each trait to its (local) implementations. -fn encode_impls(ecx: &mut EncodeContext, krate: &hir::Crate) { +fn encode_impls(ecx: &mut EncodeContext) { let mut visitor = ImplVisitor { tcx: ecx.tcx, impls: FnvHashMap() }; - krate.visit_all_items(&mut visitor); + ecx.tcx.map.krate().visit_all_items(&mut visitor); ecx.start_tag(tag_impls); - for (trait_, trait_impls) in visitor.impls { - ecx.start_tag(tag_impls_trait); - encode_def_id(ecx, trait_); - for impl_ in trait_impls { - ecx.wr_tagged_u64(tag_impls_trait_impl, def_to_u64(impl_)); - } + for (trait_def_id, trait_impls) in visitor.impls { + // FIXME(eddyb) Avoid wrapping the entries in docs. + ecx.start_tag(0); + (trait_def_id.krate.as_u32(), trait_def_id.index).encode(ecx).unwrap(); + trait_impls.encode(ecx).unwrap(); ecx.end_tag(); } ecx.end_tag(); @@ -1673,74 +1515,32 @@ fn encode_impls(ecx: &mut EncodeContext, krate: &hir::Crate) { // definition (as that's not defined in this crate). fn encode_reachable(ecx: &mut EncodeContext) { ecx.start_tag(tag_reachable_ids); - for &id in ecx.reachable { - let def_id = ecx.tcx.map.local_def_id(id); - ecx.wr_tagged_u32(tag_reachable_id, def_id.index.as_u32()); - } - ecx.end_tag(); -} - -fn encode_crate_dep(ecx: &mut EncodeContext, - dep: &cstore::CrateMetadata) { - ecx.start_tag(tag_crate_dep); - ecx.wr_tagged_str(tag_crate_dep_crate_name, &dep.name()); - let hash = decoder::get_crate_hash(dep.data()); - ecx.wr_tagged_u64(tag_crate_dep_hash, hash.as_u64()); - ecx.wr_tagged_u8(tag_crate_dep_explicitly_linked, - dep.explicitly_linked.get() as u8); - ecx.end_tag(); -} - -fn encode_hash(ecx: &mut EncodeContext, hash: &Svh) { - ecx.wr_tagged_u64(tag_crate_hash, hash.as_u64()); -} - -fn encode_rustc_version(ecx: &mut EncodeContext) { - ecx.wr_tagged_str(tag_rustc_version, &rustc_version()); -} -fn encode_crate_name(ecx: &mut EncodeContext, crate_name: &str) { - ecx.wr_tagged_str(tag_crate_crate_name, crate_name); -} + let reachable = ecx.reachable; + ecx.seq(reachable, |ecx, &id| ecx.tcx.map.local_def_id(id).index); -fn encode_crate_disambiguator(ecx: &mut EncodeContext, crate_disambiguator: &str) { - ecx.wr_tagged_str(tag_crate_disambiguator, crate_disambiguator); -} - -fn encode_crate_triple(ecx: &mut EncodeContext, triple: &str) { - ecx.wr_tagged_str(tag_crate_triple, triple); + ecx.end_tag(); } fn encode_dylib_dependency_formats(ecx: &mut EncodeContext) { - let tag = tag_dylib_dependency_formats; + ecx.start_tag(tag_dylib_dependency_formats); match ecx.tcx.sess.dependency_formats.borrow().get(&config::CrateTypeDylib) { Some(arr) => { - let s = arr.iter().enumerate().filter_map(|(i, slot)| { - let kind = match *slot { + ecx.seq(arr, |_, slot| { + match *slot { Linkage::NotLinked | - Linkage::IncludedFromDylib => return None, - Linkage::Dynamic => "d", - Linkage::Static => "s", - }; - Some(format!("{}:{}", i + 1, kind)) - }).collect::>(); - ecx.wr_tagged_str(tag, &s.join(",")); - } - None => { - ecx.wr_tagged_str(tag, ""); - } - } -} + Linkage::IncludedFromDylib => None, -fn encode_panic_strategy(ecx: &mut EncodeContext) { - match ecx.tcx.sess.opts.cg.panic { - PanicStrategy::Unwind => { - ecx.wr_tagged_u8(tag_panic_strategy, b'U'); + Linkage::Dynamic => Some(LinkagePreference::RequireDynamic), + Linkage::Static => Some(LinkagePreference::RequireStatic), + } + }); } - PanicStrategy::Abort => { - ecx.wr_tagged_u8(tag_panic_strategy, b'A'); + None => { + <[Option]>::encode(&[], ecx).unwrap(); } } + ecx.end_tag(); } pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -1764,6 +1564,7 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, reachable: reachable, mir_map: mir_map, type_shorthands: Default::default(), + xrefs: Default::default() }); // RBML compacts the encoded bytes whenever appropriate, @@ -1806,24 +1607,34 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } fn encode_metadata_inner(ecx: &mut EncodeContext) { - encode_rustc_version(ecx); + ecx.wr_tagged_str(tag_rustc_version, &rustc_version()); let tcx = ecx.tcx; let link_meta = ecx.link_meta; - encode_crate_name(ecx, &link_meta.crate_name); - encode_crate_triple(ecx, &tcx.sess.opts.target_triple); - encode_hash(ecx, &link_meta.crate_hash); - encode_crate_disambiguator(ecx, &tcx.sess.local_crate_disambiguator()); + + ecx.start_tag(tag_crate_crate_name); + link_meta.crate_name.encode(ecx).unwrap(); + ecx.end_tag(); + + ecx.start_tag(tag_crate_triple); + tcx.sess.opts.target_triple.encode(ecx).unwrap(); + ecx.end_tag(); + + ecx.start_tag(tag_crate_hash); + link_meta.crate_hash.encode(ecx).unwrap(); + ecx.end_tag(); + + ecx.start_tag(tag_crate_disambiguator); + tcx.sess.local_crate_disambiguator().encode(ecx).unwrap(); + ecx.end_tag(); + encode_dylib_dependency_formats(ecx); - encode_panic_strategy(ecx); - let krate = tcx.map.krate(); + ecx.start_tag(tag_panic_strategy); + ecx.tcx.sess.opts.cg.panic.encode(ecx); + ecx.end_tag(); let mut i = ecx.position(); - encode_attributes(ecx, &krate.attrs); - let attr_bytes = ecx.position() - i; - - i = ecx.position(); encode_crate_deps(ecx, ecx.cstore); let dep_bytes = ecx.position() - i; @@ -1849,12 +1660,12 @@ fn encode_metadata_inner(ecx: &mut EncodeContext) { // Encode macro definitions i = ecx.position(); - encode_macro_defs(ecx, krate); + encode_macro_defs(ecx); let macro_defs_bytes = ecx.position() - i; // Encode the def IDs of impls, for coherence checking. i = ecx.position(); - encode_impls(ecx, krate); + encode_impls(ecx); let impl_bytes = ecx.position() - i; // Encode reachability info. @@ -1865,7 +1676,7 @@ fn encode_metadata_inner(ecx: &mut EncodeContext) { // Encode and index the items. ecx.start_tag(tag_items); i = ecx.position(); - let (items, xrefs) = encode_info_for_items(ecx); + let items = encode_info_for_items(ecx); let item_bytes = ecx.position() - i; ecx.end_tag(); @@ -1874,11 +1685,9 @@ fn encode_metadata_inner(ecx: &mut EncodeContext) { let index_bytes = ecx.position() - i; i = ecx.position(); - encode_xrefs(ecx, xrefs); + ecx.encode_xrefs(); let xref_bytes = ecx.position() - i; - encode_struct_field_attrs(ecx, krate); - let total_bytes = ecx.position(); if ecx.tcx.sess.meta_stats() { @@ -1890,7 +1699,6 @@ fn encode_metadata_inner(ecx: &mut EncodeContext) { } println!("metadata stats:"); - println!(" attribute bytes: {}", attr_bytes); println!(" dep bytes: {}", dep_bytes); println!(" lang item bytes: {}", lang_item_bytes); println!(" native bytes: {}", native_lib_bytes); diff --git a/src/librustc_metadata/index_builder.rs b/src/librustc_metadata/index_builder.rs index fd25128575f1a..2cfa6f8d5d115 100644 --- a/src/librustc_metadata/index_builder.rs +++ b/src/librustc_metadata/index_builder.rs @@ -38,17 +38,11 @@ //! //! What record will do is to (a) record the current offset, (b) emit //! the `common::data_item` tag, and then call `callback_fn` with the -//! given data as well as an `ItemContentBuilder`. Once `callback_fn` +//! given data as well as the `EncodingContext`. Once `callback_fn` //! returns, the `common::data_item` tag will be closed. //! -//! The `ItemContentBuilder` is another type that just offers access -//! to the `ecx` that was given in, as well as maintaining a list of -//! `xref` instances, which are used to extract common data so it is -//! not re-serialized. -//! -//! `ItemContentBuilder` is a distinct type which does not offer the -//! `record` method, so that we can ensure that `common::data_item` elements -//! are never nested. +//! `EncodingContext` does not offer the `record` method, so that we +//! can ensure that `common::data_item` elements are never nested. //! //! In addition, while the `callback_fn` is executing, we will push a //! task `MetaData(some_def_id)`, which can then observe the @@ -67,8 +61,7 @@ use index::IndexData; use rustc::dep_graph::DepNode; use rustc::hir; use rustc::hir::def_id::DefId; -use rustc::ty::{self, TyCtxt}; -use rustc_data_structures::fnv::FnvHashMap; +use rustc::ty::TyCtxt; use syntax::ast; use std::ops::{Deref, DerefMut}; @@ -77,54 +70,27 @@ use std::ops::{Deref, DerefMut}; /// Item encoding cannot be nested. pub struct IndexBuilder<'a, 'b: 'a, 'tcx: 'b> { items: IndexData, - builder: ItemContentBuilder<'a, 'b, 'tcx>, -} - -/// Builder that can encode the content of items, but can't start a -/// new item itself. Most code is attached to here. -pub struct ItemContentBuilder<'a, 'b: 'a, 'tcx: 'b> { - xrefs: FnvHashMap, u32>, // sequentially-assigned pub ecx: &'a mut EncodeContext<'b, 'tcx>, } impl<'a, 'b, 'tcx> Deref for IndexBuilder<'a, 'b, 'tcx> { - type Target = EncodeContext<'b, 'tcx>; - fn deref(&self) -> &Self::Target { - self.builder.ecx - } -} - -impl<'a, 'b, 'tcx> DerefMut for IndexBuilder<'a, 'b, 'tcx> { - fn deref_mut(&mut self) -> &mut Self::Target { - self.builder.ecx - } -} - -impl<'a, 'b, 'tcx> Deref for ItemContentBuilder<'a, 'b, 'tcx> { type Target = EncodeContext<'b, 'tcx>; fn deref(&self) -> &Self::Target { self.ecx } } -impl<'a, 'b, 'tcx> DerefMut for ItemContentBuilder<'a, 'b, 'tcx> { +impl<'a, 'b, 'tcx> DerefMut for IndexBuilder<'a, 'b, 'tcx> { fn deref_mut(&mut self) -> &mut Self::Target { self.ecx } } -/// "interned" entries referenced by id -#[derive(PartialEq, Eq, Hash)] -pub enum XRef<'tcx> { Predicate(ty::Predicate<'tcx>) } - impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { pub fn new(ecx: &'a mut EncodeContext<'b, 'tcx>) -> Self { IndexBuilder { items: IndexData::new(ecx.tcx.map.num_local_def_ids()), - builder: ItemContentBuilder { - ecx: ecx, - xrefs: FnvHashMap(), - }, + ecx: ecx, } } @@ -147,28 +113,21 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { /// content system. pub fn record(&mut self, id: DefId, - op: fn(&mut ItemContentBuilder<'a, 'b, 'tcx>, DATA), + op: fn(&mut EncodeContext<'b, 'tcx>, DATA), data: DATA) where DATA: DepGraphRead { - let position = self.builder.ecx.mark_stable_position(); + let position = self.ecx.mark_stable_position(); self.items.record(id, position); let _task = self.tcx.dep_graph.in_task(DepNode::MetaData(id)); - self.builder.ecx.start_tag(tag_items_data_item).unwrap(); + self.ecx.start_tag(tag_items_data_item).unwrap(); data.read(self.tcx); - op(&mut self.builder, data); - self.builder.ecx.end_tag().unwrap(); - } - - pub fn into_fields(self) -> (IndexData, FnvHashMap, u32>) { - (self.items, self.builder.xrefs) + op(&mut self.ecx, data); + self.ecx.end_tag().unwrap(); } -} -impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> { - pub fn add_xref(&mut self, xref: XRef<'tcx>) -> u32 { - let old_len = self.xrefs.len() as u32; - *self.xrefs.entry(xref).or_insert(old_len) + pub fn into_items(self) -> IndexData { + self.items } } diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs index e5f7aab38c364..b7125daa4ad57 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -17,6 +17,7 @@ html_root_url = "https://doc.rust-lang.org/nightly/")] #![cfg_attr(not(stage0), deny(warnings))] +#![feature(conservative_impl_trait)] #![feature(core_intrinsics)] #![feature(box_patterns)] #![feature(dotdot_in_tuple_patterns)] diff --git a/src/librustc_metadata/rbml/reader.rs b/src/librustc_metadata/rbml/reader.rs index 9bbeb73ce3eca..24a0329602beb 100644 --- a/src/librustc_metadata/rbml/reader.rs +++ b/src/librustc_metadata/rbml/reader.rs @@ -80,19 +80,16 @@ impl<'doc> Doc<'doc> { } pub fn get(&self, tag: usize) -> Doc<'doc> { - get_doc(*self, tag) - } - - pub fn is_empty(&self) -> bool { - self.start == self.end - } - - pub fn as_str(&self) -> &'doc str { - str::from_utf8(&self.data[self.start..self.end]).unwrap() + match maybe_get_doc(*self, tag) { + Some(d) => d, + None => { + bug!("failed to find block with tag {:?}", tag); + } + } } - pub fn to_string(&self) -> String { - self.as_str().to_string() + pub fn children(self) -> DocsIterator<'doc> { + DocsIterator { d: self } } } @@ -129,7 +126,7 @@ pub struct Res { pub next: usize, } -pub fn tag_at(data: &[u8], start: usize) -> Result { +fn tag_at(data: &[u8], start: usize) -> Result { let v = data[start] as usize; if v < 0xf0 { Ok(Res { @@ -180,7 +177,7 @@ fn vuint_at_slow(data: &[u8], start: usize) -> Result { Err(Error::IntTooBig(a as usize)) } -pub fn vuint_at(data: &[u8], start: usize) -> Result { +fn vuint_at(data: &[u8], start: usize) -> Result { if data.len() - start < 4 { return vuint_at_slow(data, start); } @@ -234,7 +231,7 @@ pub fn vuint_at(data: &[u8], start: usize) -> Result { } } -pub fn tag_len_at(data: &[u8], next: usize) -> Result { +fn tag_len_at(data: &[u8], next: usize) -> Result { vuint_at(data, next) } @@ -255,27 +252,14 @@ pub fn maybe_get_doc<'a>(d: Doc<'a>, tg: usize) -> Option> { None } -pub fn get_doc<'a>(d: Doc<'a>, tg: usize) -> Doc<'a> { - match maybe_get_doc(d, tg) { - Some(d) => d, - None => { - bug!("failed to find block with tag {:?}", tg); - } - } -} - -pub fn docs<'a>(d: Doc<'a>) -> DocsIterator<'a> { - DocsIterator { d: d } -} - pub struct DocsIterator<'a> { d: Doc<'a>, } impl<'a> Iterator for DocsIterator<'a> { - type Item = (usize, Doc<'a>); + type Item = Doc<'a>; - fn next(&mut self) -> Option<(usize, Doc<'a>)> { + fn next(&mut self) -> Option> { if self.d.start >= self.d.end { return None; } @@ -297,98 +281,10 @@ impl<'a> Iterator for DocsIterator<'a> { }; self.d.start = end; - return Some((elt_tag.val, doc)); - } -} - -pub fn tagged_docs<'a>(d: Doc<'a>, tag: usize) -> TaggedDocsIterator<'a> { - TaggedDocsIterator { - iter: docs(d), - tag: tag, + return Some(doc); } } -pub struct TaggedDocsIterator<'a> { - iter: DocsIterator<'a>, - tag: usize, -} - -impl<'a> Iterator for TaggedDocsIterator<'a> { - type Item = Doc<'a>; - - fn next(&mut self) -> Option> { - while let Some((tag, doc)) = self.iter.next() { - if tag == self.tag { - return Some(doc); - } - } - None - } -} - -pub fn with_doc_data(d: Doc, f: F) -> T - where F: FnOnce(&[u8]) -> T -{ - f(&d.data[d.start..d.end]) -} - -pub fn doc_as_u8(d: Doc) -> u8 { - assert_eq!(d.end, d.start + 1); - d.data[d.start] -} - -pub fn doc_as_u64(d: Doc) -> u64 { - if d.end >= 8 { - // For performance, we read 8 big-endian bytes, - // and mask off the junk if there is any. This - // obviously won't work on the first 8 bytes - // of a file - we will fall of the start - // of the page and segfault. - - let mut b = [0; 8]; - b.copy_from_slice(&d.data[d.end - 8..d.end]); - let data = unsafe { (*(b.as_ptr() as *const u64)).to_be() }; - let len = d.end - d.start; - if len < 8 { - data & ((1 << (len * 8)) - 1) - } else { - data - } - } else { - let mut result = 0; - for b in &d.data[d.start..d.end] { - result = (result << 8) + (*b as u64); - } - result - } -} - -#[inline] -pub fn doc_as_u16(d: Doc) -> u16 { - doc_as_u64(d) as u16 -} -#[inline] -pub fn doc_as_u32(d: Doc) -> u32 { - doc_as_u64(d) as u32 -} - -#[inline] -pub fn doc_as_i8(d: Doc) -> i8 { - doc_as_u8(d) as i8 -} -#[inline] -pub fn doc_as_i16(d: Doc) -> i16 { - doc_as_u16(d) as i16 -} -#[inline] -pub fn doc_as_i32(d: Doc) -> i32 { - doc_as_u32(d) as i32 -} -#[inline] -pub fn doc_as_i64(d: Doc) -> i64 { - doc_as_u64(d) as i64 -} - #[test] fn test_vuint_at() { let data = &[ diff --git a/src/librustc_metadata/rbml/writer.rs b/src/librustc_metadata/rbml/writer.rs index 94e9b394f1f90..46b63cb134031 100644 --- a/src/librustc_metadata/rbml/writer.rs +++ b/src/librustc_metadata/rbml/writer.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::mem; use std::io::prelude::*; use std::io::{self, SeekFrom, Cursor}; @@ -112,50 +111,10 @@ impl<'a> Encoder<'a> { Ok(()) } - pub fn wr_tag(&mut self, tag_id: usize, blk: F) -> EncodeResult - where F: FnOnce() -> EncodeResult - { - self.start_tag(tag_id)?; - blk()?; - self.end_tag() - } - - pub fn wr_tagged_bytes(&mut self, tag_id: usize, b: &[u8]) -> EncodeResult { - write_tag(&mut self.opaque.cursor, tag_id)?; - write_vuint(&mut self.opaque.cursor, b.len())?; - self.opaque.cursor.write_all(b) - } - - pub fn wr_tagged_u64(&mut self, tag_id: usize, v: u64) -> EncodeResult { - let bytes: [u8; 8] = unsafe { mem::transmute(v.to_be()) }; - // tagged integers are emitted in big-endian, with no - // leading zeros. - let leading_zero_bytes = v.leading_zeros() / 8; - self.wr_tagged_bytes(tag_id, &bytes[leading_zero_bytes as usize..]) - } - - #[inline] - pub fn wr_tagged_u32(&mut self, tag_id: usize, v: u32) -> EncodeResult { - self.wr_tagged_u64(tag_id, v as u64) - } - - #[inline] - pub fn wr_tagged_u8(&mut self, tag_id: usize, v: u8) -> EncodeResult { - self.wr_tagged_bytes(tag_id, &[v]) - } - pub fn wr_tagged_str(&mut self, tag_id: usize, v: &str) -> EncodeResult { - self.wr_tagged_bytes(tag_id, v.as_bytes()) - } - - pub fn wr_bytes(&mut self, b: &[u8]) -> EncodeResult { - debug!("Write {:?} bytes", b.len()); - self.opaque.cursor.write_all(b) - } - - pub fn wr_str(&mut self, s: &str) -> EncodeResult { - debug!("Write str: {:?}", s); - self.opaque.cursor.write_all(s.as_bytes()) + write_tag(&mut self.opaque.cursor, tag_id)?; + write_vuint(&mut self.opaque.cursor, v.len())?; + self.opaque.cursor.write_all(v.as_bytes()) } pub fn position(&mut self) -> usize { diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 83f03e7cfc5ac..3df3a2decba3b 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -21,10 +21,10 @@ use ParentLink::{ModuleParentLink, BlockParentLink}; use Resolver; use {resolve_error, resolve_struct_error, ResolutionError}; -use rustc::middle::cstore::{ChildItem, DlDef}; +use rustc::middle::cstore::ChildItem; use rustc::hir::def::*; use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId}; -use rustc::ty::{self, VariantKind}; +use rustc::ty; use std::cell::Cell; @@ -201,7 +201,7 @@ impl<'b> Resolver<'b> { let module = self.new_extern_crate_module(parent_link, def, item.id); self.define(parent, name, TypeNS, (module, sp, vis)); - self.build_reduced_graph_for_external_crate(module); + self.populate_module_if_necessary(module); } } @@ -388,13 +388,8 @@ impl<'b> Resolver<'b> { } /// Builds the reduced graph for a single item in an external crate. - fn build_reduced_graph_for_external_crate_def(&mut self, parent: Module<'b>, xcdef: ChildItem) { - let def = match xcdef.def { - DlDef(def) => def, - _ => return, - }; - - if let Def::ForeignMod(def_id) = def { + fn build_reduced_graph_for_external_crate_def(&mut self, parent: Module<'b>, child: ChildItem) { + if let Def::ForeignMod(def_id) = child.def { // Foreign modules have no names. Recur and populate eagerly. for child in self.session.cstore.item_children(def_id) { self.build_reduced_graph_for_external_crate_def(parent, child); @@ -402,8 +397,9 @@ impl<'b> Resolver<'b> { return; } - let name = xcdef.name; - let vis = if parent.is_trait() { ty::Visibility::Public } else { xcdef.vis }; + let def = child.def; + let name = child.name; + let vis = if parent.is_trait() { ty::Visibility::Public } else { child.vis }; match def { Def::Mod(_) | Def::ForeignMod(_) | Def::Enum(..) => { @@ -413,16 +409,12 @@ impl<'b> Resolver<'b> { let module = self.new_module(parent_link, Some(def), None); let _ = self.try_define(parent, name, TypeNS, (module, DUMMY_SP, vis)); } - Def::Variant(_, variant_id) => { + Def::Variant(..) => { debug!("(building reduced graph for external crate) building variant {}", name); // Variants are always treated as importable to allow them to be glob used. // All variants are defined in both type and value namespaces as future-proofing. let _ = self.try_define(parent, name, TypeNS, (def, DUMMY_SP, vis)); let _ = self.try_define(parent, name, ValueNS, (def, DUMMY_SP, vis)); - if self.session.cstore.variant_kind(variant_id) == Some(VariantKind::Struct) { - // Not adding fields for variants as they are not accessed with a self receiver - self.structs.insert(variant_id, Vec::new()); - } } Def::Fn(..) | Def::Static(..) | @@ -439,7 +431,7 @@ impl<'b> Resolver<'b> { // If this is a trait, add all the trait item names to the trait // info. - let trait_item_def_ids = self.session.cstore.trait_item_def_ids(def_id); + let trait_item_def_ids = self.session.cstore.impl_or_trait_items(def_id); for trait_item_def in &trait_item_def_ids { let trait_item_name = self.session.cstore.item_name(trait_item_def.def_id()); @@ -493,15 +485,6 @@ impl<'b> Resolver<'b> { } } - /// Builds the reduced graph rooted at the 'use' directive for an external - /// crate. - fn build_reduced_graph_for_external_crate(&mut self, root: Module<'b>) { - let root_cnum = root.def_id().unwrap().krate; - for child in self.session.cstore.crate_top_level_items(root_cnum) { - self.build_reduced_graph_for_external_crate_def(root, child); - } - } - /// Ensures that the reduced graph rooted at the given external module /// is built, building it if it is not. pub fn populate_module_if_necessary(&mut self, module: Module<'b>) { diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 5e78ac7ca94c7..b03e76c829a3e 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1275,6 +1275,7 @@ impl<'a> Resolver<'a> { -> Module<'a> { let mut module = ModuleS::new(parent_link, Some(def), Some(local_node_id)); module.extern_crate_id = Some(local_node_id); + module.populated.set(false); self.arenas.modules.alloc(module) } diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 3764e26b020db..186183a8ad4d4 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -543,10 +543,8 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { .map(|mr| mr.def_id()) } ty::ImplContainer(def_id) => { - let impl_items = self.tcx.impl_items.borrow(); - Some(impl_items.get(&def_id) - .unwrap() - .iter() + let impl_items = self.tcx.impl_or_trait_items(def_id); + Some(impl_items.iter() .find(|mr| { self.tcx.impl_or_trait_item(mr.def_id()).name() == ti.name() diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index a58de71ca41ed..b9449eeecf427 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -627,25 +627,23 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { fn can_result_in_trans_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> bool { - if !match tcx.lookup_item_type(def_id).ty.sty { - ty::TyFnDef(def_id, ..) => { + match tcx.lookup_item_type(def_id).ty.sty { + ty::TyFnDef(def_id, _, f) => { // Some constructors also have type TyFnDef but they are // always instantiated inline and don't result in // translation item. Same for FFI functions. - match tcx.map.get_if_local(def_id) { - Some(hir_map::NodeVariant(_)) | - Some(hir_map::NodeStructCtor(_)) | - Some(hir_map::NodeForeignItem(_)) => false, - Some(_) => true, - None => { - tcx.sess.cstore.variant_kind(def_id).is_none() + if let Some(hir_map::NodeForeignItem(_)) = tcx.map.get_if_local(def_id) { + return false; + } + + if let Some(adt_def) = f.sig.output().skip_binder().ty_adt_def() { + if adt_def.variants.iter().any(|v| def_id == v.did) { + return false; } } } - ty::TyClosure(..) => true, - _ => false - } { - return false; + ty::TyClosure(..) => {} + _ => return false } can_have_local_instance(tcx, def_id) diff --git a/src/librustc_trans/meth.rs b/src/librustc_trans/meth.rs index ee2f24d21e07c..9db5020747e1f 100644 --- a/src/librustc_trans/meth.rs +++ b/src/librustc_trans/meth.rs @@ -230,7 +230,7 @@ pub fn get_vtable_methods<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx.populate_implementations_for_trait_if_necessary(trait_id); - let trait_item_def_ids = tcx.trait_item_def_ids(trait_id); + let trait_item_def_ids = tcx.impl_or_trait_items(trait_id); trait_item_def_ids .iter() diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index e9f324c0b08f0..999433db24071 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -247,11 +247,17 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { let vtable = common::fulfill_obligation(ccx.shared(), DUMMY_SP, trait_ref); if let traits::VtableImpl(vtable_impl) = vtable { let name = ccx.tcx().item_name(instance.def); - for ac in ccx.tcx().associated_consts(vtable_impl.impl_def_id) { - if ac.name == name { - instance = Instance::new(ac.def_id, vtable_impl.substs); - break; - } + let ac = ccx.tcx().impl_or_trait_items(vtable_impl.impl_def_id) + .iter().filter_map(|id| { + match *id { + ty::ConstTraitItemId(def_id) => { + Some(ccx.tcx().impl_or_trait_item(def_id)) + } + _ => None + } + }).find(|ic| ic.name() == name); + if let Some(ac) = ac { + instance = Instance::new(ac.def_id(), vtable_impl.substs); } } } diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index bcb410e1b8d01..71219d82668e4 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -218,7 +218,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Trait must have a method named `m_name` and it should not have // type parameters or early-bound regions. let tcx = self.tcx; - let method_item = self.trait_item(trait_def_id, m_name).unwrap(); + let method_item = self.impl_or_trait_item(trait_def_id, m_name).unwrap(); let method_ty = method_item.as_opt_method().unwrap(); assert_eq!(method_ty.generics.types.len(), 0); assert_eq!(method_ty.generics.regions.len(), 0); @@ -359,27 +359,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { Ok(def) } - /// Find item with name `item_name` defined in `trait_def_id` - /// and return it, or `None`, if no such item. - pub fn trait_item(&self, - trait_def_id: DefId, - item_name: ast::Name) - -> Option> + /// Find item with name `item_name` defined in impl/trait `def_id` + /// and return it, or `None`, if no such item was defined there. + pub fn impl_or_trait_item(&self, + def_id: DefId, + item_name: ast::Name) + -> Option> { - let trait_items = self.tcx.trait_items(trait_def_id); - trait_items.iter() - .find(|item| item.name() == item_name) - .cloned() - } - - pub fn impl_item(&self, - impl_def_id: DefId, - item_name: ast::Name) - -> Option> - { - let impl_items = self.tcx.impl_items.borrow(); - let impl_items = impl_items.get(&impl_def_id).unwrap(); - impl_items + self.tcx.impl_or_trait_items(def_id) .iter() .map(|&did| self.tcx.impl_or_trait_item(did.def_id())) .find(|m| m.name() == item_name) diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 81e95c91e7ff9..9fba9bcb757b6 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -403,7 +403,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { debug!("assemble_inherent_impl_probe {:?}", impl_def_id); - let item = match self.impl_item(impl_def_id) { + let item = match self.impl_or_trait_item(impl_def_id) { Some(m) => m, None => { return; } // No method with correct name on this impl }; @@ -555,7 +555,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { let tcx = self.tcx; for bound_trait_ref in traits::transitive_bounds(tcx, bounds) { - let item = match self.trait_item(bound_trait_ref.def_id()) { + let item = match self.impl_or_trait_item(bound_trait_ref.def_id()) { Some(v) => v, None => { continue; } }; @@ -1292,18 +1292,12 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { self.tcx.erase_late_bound_regions(value) } - fn impl_item(&self, impl_def_id: DefId) - -> Option> + /// Find item with name `item_name` defined in impl/trait `def_id` + /// and return it, or `None`, if no such item was defined there. + fn impl_or_trait_item(&self, def_id: DefId) + -> Option> { - self.fcx.impl_item(impl_def_id, self.item_name) - } - - /// Find item with name `item_name` defined in `trait_def_id` - /// and return it, or `None`, if no such item. - fn trait_item(&self, trait_def_id: DefId) - -> Option> - { - self.fcx.trait_item(trait_def_id, self.item_name) + self.fcx.impl_or_trait_item(def_id, self.item_name) } } diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 3692d6fbf73d6..7ec4918070233 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -16,9 +16,8 @@ use CrateCtxt; use check::{FnCtxt}; use rustc::hir::map as hir_map; use rustc::ty::{self, Ty, ToPolyTraitRef, ToPredicate, TypeFoldable}; -use middle::cstore; use hir::def::Def; -use hir::def_id::DefId; +use hir::def_id::{CRATE_DEF_INDEX, DefId}; use middle::lang_items::FnOnceTraitLangItem; use rustc::ty::subst::Substs; use rustc::traits::{Obligation, SelectionContext}; @@ -92,9 +91,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { CandidateSource::ImplSource(impl_did) => { // Provide the best span we can. Use the item, if local to crate, else // the impl, if local to crate (item may be defaulted), else nothing. - let item = self.impl_item(impl_did, item_name) + let item = self.impl_or_trait_item(impl_did, item_name) .or_else(|| { - self.trait_item( + self.impl_or_trait_item( self.tcx.impl_trait_ref(impl_did).unwrap().def_id, item_name @@ -127,7 +126,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } CandidateSource::TraitSource(trait_did) => { - let item = self.trait_item(trait_did, item_name).unwrap(); + let item = self.impl_or_trait_item(trait_did, item_name).unwrap(); let item_span = self.tcx.map.def_id_span(item.def_id(), span); span_note!(err, item_span, "candidate #{} is defined in the trait `{}`", @@ -321,7 +320,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // implementing a trait would be legal but is rejected // here). (type_is_local || info.def_id.is_local()) - && self.trait_item(info.def_id, item_name).is_some() + && self.impl_or_trait_item(info.def_id, item_name).is_some() }) .collect::>(); @@ -449,34 +448,30 @@ pub fn all_traits<'a>(ccx: &'a CrateCtxt) -> AllTraits<'a> { // Cross-crate: let mut external_mods = FnvHashSet(); - fn handle_external_def(traits: &mut AllTraitsVec, + fn handle_external_def(ccx: &CrateCtxt, + traits: &mut AllTraitsVec, external_mods: &mut FnvHashSet, - ccx: &CrateCtxt, - cstore: &for<'a> cstore::CrateStore<'a>, - dl: cstore::DefLike) { - match dl { - cstore::DlDef(Def::Trait(did)) => { + def: Def) { + match def { + Def::Trait(did) => { traits.push(TraitInfo::new(did)); } - cstore::DlDef(Def::Mod(did)) => { + Def::Mod(did) => { if !external_mods.insert(did) { return; } - for child in cstore.item_children(did) { - handle_external_def(traits, external_mods, - ccx, cstore, child.def) + for child in ccx.tcx.sess.cstore.item_children(did) { + handle_external_def(ccx, traits, external_mods, child.def) } } _ => {} } } - let cstore = &*ccx.tcx.sess.cstore; - for cnum in ccx.tcx.sess.cstore.crates() { - for child in cstore.crate_top_level_items(cnum) { - handle_external_def(&mut traits, &mut external_mods, - ccx, cstore, child.def) - } + handle_external_def(ccx, &mut traits, &mut external_mods, Def::Mod(DefId { + krate: cnum, + index: CRATE_DEF_INDEX + })); } *ccx.all_traits.borrow_mut() = Some(traits); diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index 26c33c00b9cf9..fb077d279c998 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -39,6 +39,8 @@ use rustc::hir::intravisit; use rustc::hir::{Item, ItemImpl}; use rustc::hir; +use std::rc::Rc; + mod orphan; mod overlap; mod unsafety; @@ -156,7 +158,7 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> { } } - tcx.impl_items.borrow_mut().insert(impl_did, impl_items); + tcx.impl_or_trait_item_ids.borrow_mut().insert(impl_did, Rc::new(impl_items)); } fn add_inherent_impl(&self, base_def_id: DefId, impl_def_id: DefId) { @@ -208,7 +210,7 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> { tcx.populate_implementations_for_trait_if_necessary(drop_trait); let drop_trait = tcx.lookup_trait_def(drop_trait); - let impl_items = tcx.impl_items.borrow(); + let impl_items = tcx.impl_or_trait_item_ids.borrow(); drop_trait.for_each_impl(tcx, |impl_did| { let items = impl_items.get(&impl_did).unwrap(); diff --git a/src/librustc_typeck/coherence/overlap.rs b/src/librustc_typeck/coherence/overlap.rs index 890b6c72e6fee..9d072491cc28b 100644 --- a/src/librustc_typeck/coherence/overlap.rs +++ b/src/librustc_typeck/coherence/overlap.rs @@ -55,12 +55,12 @@ impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> { }) } - let impl_items = self.tcx.impl_items.borrow(); + let impl_items = self.tcx.impl_or_trait_item_ids.borrow(); - for item1 in &impl_items[&impl1] { + for item1 in &impl_items[&impl1][..] { let (name, namespace) = name_and_namespace(self.tcx, item1); - for item2 in &impl_items[&impl2] { + for item2 in &impl_items[&impl2][..] { if (name, namespace) == name_and_namespace(self.tcx, item2) { let msg = format!("duplicate definitions with name `{}`", name); let node_id = self.tcx.map.as_local_node_id(item1.def_id()).unwrap(); diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 04aca8c0947ca..fa052bec7be3d 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -563,6 +563,7 @@ fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, vis: &hir::Visibility, sig: &hir::MethodSig, defaultness: hir::Defaultness, + has_body: bool, untransformed_rcvr_ty: Ty<'tcx>, rcvr_ty_predicates: &ty::GenericPredicates<'tcx>) { let def_id = ccx.tcx.map.local_def_id(id); @@ -580,15 +581,18 @@ fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, sig, untransformed_rcvr_ty, anon_scope) }; - let ty_method = ty::Method::new(name, - ty_generics, - ty_generic_predicates, - fty, - explicit_self_category, - ty::Visibility::from_hir(vis, id, ccx.tcx), - defaultness, - def_id, - container); + let ty_method = ty::Method { + name: name, + generics: ty_generics, + predicates: ty_generic_predicates, + fty: fty, + explicit_self: explicit_self_category, + vis: ty::Visibility::from_hir(vis, id, ccx.tcx), + defaultness: defaultness, + has_body: has_body, + def_id: def_id, + container: container, + }; let substs = mk_item_substs(&ccx.icx(&(rcvr_ty_predicates, &sig.generics)), ccx.tcx.map.span(id), def_id); @@ -843,7 +847,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { convert_method(ccx, ImplContainer(def_id), impl_item.name, impl_item.id, method_vis, - sig, impl_item.defaultness, selfty, + sig, impl_item.defaultness, true, selfty, &ty_predicates); } } @@ -905,7 +909,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { // Convert all the methods for trait_item in trait_items { - if let hir::MethodTraitItem(ref sig, _) = trait_item.node { + if let hir::MethodTraitItem(ref sig, ref body) = trait_item.node { convert_method(ccx, container, trait_item.name, @@ -913,6 +917,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { &hir::Inherited, sig, hir::Defaultness::Default, + body.is_some(), tcx.mk_self_type(), &trait_predicates); @@ -928,8 +933,8 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { hir::TypeTraitItem(..) => ty::TypeTraitItemId(def_id) } }).collect()); - tcx.trait_item_def_ids.borrow_mut().insert(ccx.tcx.map.local_def_id(it.id), - trait_item_def_ids); + tcx.impl_or_trait_item_ids.borrow_mut().insert(ccx.tcx.map.local_def_id(it.id), + trait_item_def_ids); }, hir::ItemStruct(ref struct_def, _) | hir::ItemUnion(ref struct_def, _) => { diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 709e36989244f..e992861b77bc6 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -15,7 +15,6 @@ use std::iter::once; use syntax::ast; use rustc::hir; -use rustc::middle::cstore; use rustc::hir::def::Def; use rustc::hir::def_id::DefId; use rustc::hir::print as pprust; @@ -96,12 +95,12 @@ fn try_inline_def<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>, Def::TyAlias(did) => { record_extern_fqn(cx, did, clean::TypeTypedef); ret.extend(build_impls(cx, tcx, did)); - build_type(cx, tcx, did) + clean::TypedefItem(build_type_alias(cx, tcx, did), false) } Def::Enum(did) => { record_extern_fqn(cx, did, clean::TypeEnum); ret.extend(build_impls(cx, tcx, did)); - build_type(cx, tcx, did) + clean::EnumItem(build_enum(cx, tcx, did)) } // Assume that the enum type is reexported next to the variant, and // variants don't show up in documentation specially. @@ -200,6 +199,18 @@ fn build_external_function<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx } } +fn build_enum<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>, + did: DefId) -> clean::Enum { + let t = tcx.lookup_item_type(did); + let predicates = tcx.lookup_predicates(did); + + clean::Enum { + generics: (t.generics, &predicates).clean(cx), + variants_stripped: false, + variants: tcx.lookup_adt_def(did).variants.clean(cx), + } +} + fn build_struct<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>, did: DefId) -> clean::Struct { let t = tcx.lookup_item_type(did); @@ -232,25 +243,15 @@ fn build_union<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>, } } -fn build_type<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>, - did: DefId) -> clean::ItemEnum { +fn build_type_alias<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>, + did: DefId) -> clean::Typedef { let t = tcx.lookup_item_type(did); let predicates = tcx.lookup_predicates(did); - match t.ty.sty { - ty::TyAdt(edef, _) if edef.is_enum() && !tcx.sess.cstore.is_typedef(did) => { - return clean::EnumItem(clean::Enum { - generics: (t.generics, &predicates).clean(cx), - variants_stripped: false, - variants: edef.variants.clean(cx), - }) - } - _ => {} - } - clean::TypedefItem(clean::Typedef { + clean::Typedef { type_: t.ty.clean(cx), generics: (t.generics, &predicates).clean(cx), - }, false) + } } pub fn build_impls<'a, 'tcx>(cx: &DocContext, @@ -264,32 +265,49 @@ pub fn build_impls<'a, 'tcx>(cx: &DocContext, build_impl(cx, tcx, did, &mut impls); } } - - // If this is the first time we've inlined something from this crate, then - // we inline *all* impls from the crate into this crate. Note that there's + // If this is the first time we've inlined something from another crate, then + // we inline *all* impls from all the crates into this crate. Note that there's // currently no way for us to filter this based on type, and we likely need // many impls for a variety of reasons. // // Primarily, the impls will be used to populate the documentation for this // type being inlined, but impls can also be used when generating // documentation for primitives (no way to find those specifically). - if cx.populated_crate_impls.borrow_mut().insert(did.krate) { - for item in tcx.sess.cstore.crate_top_level_items(did.krate) { - populate_impls(cx, tcx, item.def, &mut impls); - } + if cx.populated_all_crate_impls.get() { + return impls; + } - fn populate_impls<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>, - def: cstore::DefLike, - impls: &mut Vec) { - match def { - cstore::DlImpl(did) => build_impl(cx, tcx, did, impls), - cstore::DlDef(Def::Mod(did)) => { - for item in tcx.sess.cstore.item_children(did) { - populate_impls(cx, tcx, item.def, impls) - } - } - _ => {} - } + cx.populated_all_crate_impls.set(true); + + for did in tcx.sess.cstore.implementations_of_trait(None) { + build_impl(cx, tcx, did, &mut impls); + } + + // Also try to inline primitive impls from other crates. + let primitive_impls = [ + tcx.lang_items.isize_impl(), + tcx.lang_items.i8_impl(), + tcx.lang_items.i16_impl(), + tcx.lang_items.i32_impl(), + tcx.lang_items.i64_impl(), + tcx.lang_items.usize_impl(), + tcx.lang_items.u8_impl(), + tcx.lang_items.u16_impl(), + tcx.lang_items.u32_impl(), + tcx.lang_items.u64_impl(), + tcx.lang_items.f32_impl(), + tcx.lang_items.f64_impl(), + tcx.lang_items.char_impl(), + tcx.lang_items.str_impl(), + tcx.lang_items.slice_impl(), + tcx.lang_items.slice_impl(), + tcx.lang_items.const_ptr_impl() + ]; + + for def_id in primitive_impls.iter().filter_map(|&def_id| def_id) { + if !def_id.is_local() { + tcx.populate_implementations_for_primitive_if_necessary(def_id); + build_impl(cx, tcx, def_id, &mut impls); } } @@ -348,7 +366,7 @@ pub fn build_impl<'a, 'tcx>(cx: &DocContext, } let predicates = tcx.lookup_predicates(did); - let trait_items = tcx.sess.cstore.impl_items(did) + let trait_items = tcx.sess.cstore.impl_or_trait_items(did) .iter() .filter_map(|did| { let did = did.def_id(); @@ -453,7 +471,7 @@ pub fn build_impl<'a, 'tcx>(cx: &DocContext, for_: for_, generics: (ty.generics, &predicates).clean(cx), items: trait_items, - polarity: polarity.map(|p| { p.clean(cx) }), + polarity: Some(polarity.clean(cx)), }), source: clean::Span::empty(), name: None, @@ -482,19 +500,17 @@ fn build_module<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>, let mut visited = FnvHashSet(); for item in tcx.sess.cstore.item_children(did) { match item.def { - cstore::DlDef(Def::ForeignMod(did)) => { + Def::ForeignMod(did) => { fill_in(cx, tcx, did, items); } - cstore::DlDef(def) if item.vis == ty::Visibility::Public => { - if !visited.insert(def) { continue } - if let Some(i) = try_inline_def(cx, tcx, def) { - items.extend(i) + def => { + if item.vis == ty::Visibility::Public { + if !visited.insert(def) { continue } + if let Some(i) = try_inline_def(cx, tcx, def) { + items.extend(i) + } } } - cstore::DlDef(..) => {} - // All impls were inlined above - cstore::DlImpl(..) => {} - cstore::DlField => panic!("unimplemented field"), } } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 7eb7b24015e10..f9d7eb50edaec 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -33,7 +33,6 @@ use syntax::print::pprust as syntax_pprust; use syntax_pos::{self, DUMMY_SP, Pos}; use rustc_trans::back::link; -use rustc::middle::cstore; use rustc::middle::privacy::AccessLevels; use rustc::middle::resolve_lifetime::DefRegion::*; use rustc::hir::def::Def; @@ -239,9 +238,10 @@ impl Clean for CrateNum { fn clean(&self, cx: &DocContext) -> ExternalCrate { let mut primitives = Vec::new(); cx.tcx_opt().map(|tcx| { - for item in tcx.sess.cstore.crate_top_level_items(self.0) { + let root = DefId { krate: self.0, index: CRATE_DEF_INDEX }; + for item in tcx.sess.cstore.item_children(root) { let did = match item.def { - cstore::DlDef(Def::Mod(did)) => did, + Def::Mod(did) => did, _ => continue }; let attrs = inline::load_attrs(cx, tcx, did); @@ -1877,11 +1877,9 @@ impl Clean for hir::StructField { impl<'tcx> Clean for ty::FieldDefData<'tcx, 'static> { fn clean(&self, cx: &DocContext) -> Item { - // FIXME: possible O(n^2)-ness! Not my fault. - let attr_map = cx.tcx().sess.cstore.crate_struct_field_attrs(self.did.krate); Item { name: Some(self.name).clean(cx), - attrs: attr_map.get(&self.did).unwrap_or(&Vec::new()).clean(cx), + attrs: cx.tcx().get_attrs(self.did).clean(cx), source: Span::empty(), visibility: self.vis.clean(cx), stability: get_stability(cx, self.did), diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 399702003ea4f..c52497dc89bd6 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -13,13 +13,13 @@ use rustc_lint; use rustc_driver::{driver, target_features, abort_on_err}; use rustc::dep_graph::DepGraph; use rustc::session::{self, config}; -use rustc::hir::def_id::{CrateNum, DefId}; +use rustc::hir::def_id::DefId; use rustc::hir::def::Def; use rustc::middle::privacy::AccessLevels; use rustc::ty::{self, TyCtxt}; use rustc::hir::map as hir_map; use rustc::lint; -use rustc::util::nodemap::{FnvHashMap, FnvHashSet}; +use rustc::util::nodemap::FnvHashMap; use rustc_trans::back::link; use rustc_resolve as resolve; use rustc_metadata::cstore::CStore; @@ -53,7 +53,7 @@ pub struct DocContext<'a, 'tcx: 'a> { pub map: &'a hir_map::Map<'tcx>, pub maybe_typed: MaybeTyped<'a, 'tcx>, pub input: Input, - pub populated_crate_impls: RefCell>, + pub populated_all_crate_impls: Cell, pub deref_trait_did: Cell>, pub deref_mut_trait_did: Cell>, // Note that external items for which `doc(hidden)` applies to are shown as @@ -205,7 +205,7 @@ pub fn run_core(search_paths: SearchPaths, map: &tcx.map, maybe_typed: Typed(tcx), input: input, - populated_crate_impls: Default::default(), + populated_all_crate_impls: Cell::new(false), deref_trait_did: Cell::new(None), deref_mut_trait_did: Cell::new(None), access_levels: RefCell::new(access_levels), diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 3d2caeda1468d..4518945dd9857 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -106,8 +106,8 @@ pub fn run(input: &str, map: &map, maybe_typed: core::NotTyped(&sess), input: input, + populated_all_crate_impls: Cell::new(false), external_traits: Default::default(), - populated_crate_impls: Default::default(), deref_trait_did: Cell::new(None), deref_mut_trait_did: Cell::new(None), access_levels: Default::default(), diff --git a/src/librustdoc/visit_lib.rs b/src/librustdoc/visit_lib.rs index cbc556730fb63..da11f652b4b34 100644 --- a/src/librustdoc/visit_lib.rs +++ b/src/librustdoc/visit_lib.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use rustc::middle::cstore::{CrateStore, ChildItem, DefLike}; +use rustc::middle::cstore::{CrateStore, ChildItem}; use rustc::middle::privacy::{AccessLevels, AccessLevel}; use rustc::hir::def::Def; use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId}; @@ -66,39 +66,32 @@ impl<'a, 'b, 'tcx> LibEmbargoVisitor<'a, 'b, 'tcx> { pub fn visit_mod(&mut self, did: DefId) { for item in self.cstore.item_children(did) { - if let DefLike::DlDef(def) = item.def { - match def { - Def::Mod(did) | - Def::ForeignMod(did) | - Def::Trait(did) | - Def::Struct(did) | - Def::Union(did) | - Def::Enum(did) | - Def::TyAlias(did) | - Def::Fn(did) | - Def::Method(did) | - Def::Static(did, _) | - Def::Const(did) => self.visit_item(did, item), - _ => {} - } + match item.def { + Def::Mod(did) | + Def::ForeignMod(did) | + Def::Trait(did) | + Def::Struct(did) | + Def::Union(did) | + Def::Enum(did) | + Def::TyAlias(did) | + Def::Fn(did) | + Def::Method(did) | + Def::Static(did, _) | + Def::Const(did) => self.visit_item(did, item), + _ => {} } } } fn visit_item(&mut self, did: DefId, item: ChildItem) { let inherited_item_level = match item.def { - DefLike::DlImpl(..) | DefLike::DlField => unreachable!(), - DefLike::DlDef(def) => { - match def { - Def::ForeignMod(..) => self.prev_level, - _ => if item.vis == Visibility::Public { self.prev_level } else { None } - } - } + Def::ForeignMod(..) => self.prev_level, + _ => if item.vis == Visibility::Public { self.prev_level } else { None } }; let item_level = self.update(did, inherited_item_level); - if let DefLike::DlDef(Def::Mod(did)) = item.def { + if let Def::Mod(did) = item.def { let orig_level = self.prev_level; self.prev_level = item_level; From 89736e86716808801732323f3aa848b97fc2b5ba Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Mon, 5 Sep 2016 10:54:38 +0300 Subject: [PATCH 20/39] rustc: remove ImplOrTraitItemId and TraitDef's associated_type_names. --- src/librustc/dep_graph/dep_node.rs | 6 +- src/librustc/middle/cstore.rs | 4 +- src/librustc/middle/dead.rs | 7 +-- src/librustc/middle/stability.rs | 7 +-- .../traits/specialize/specialization_graph.rs | 4 +- src/librustc/ty/context.rs | 6 +- src/librustc/ty/maps.rs | 3 +- src/librustc/ty/mod.rs | 55 ++++-------------- src/librustc/ty/trait_def.rs | 7 --- src/librustc_const_eval/eval.rs | 12 ++-- src/librustc_metadata/common.rs | 3 - src/librustc_metadata/csearch.rs | 11 +++- src/librustc_metadata/decoder.rs | 27 +-------- src/librustc_metadata/encoder.rs | 17 +----- src/librustc_resolve/build_reduced_graph.rs | 4 +- src/librustc_save_analysis/lib.rs | 14 ++--- src/librustc_trans/meth.rs | 18 +++--- src/librustc_trans/mir/constant.rs | 12 ++-- src/librustc_typeck/astconv.rs | 27 +++++---- src/librustc_typeck/check/method/mod.rs | 2 +- src/librustc_typeck/check/mod.rs | 8 ++- src/librustc_typeck/coherence/mod.rs | 24 ++------ src/librustc_typeck/coherence/overlap.rs | 22 ++++---- src/librustc_typeck/collect.rs | 56 ++++++++----------- src/librustc_typeck/lib.rs | 1 + src/librustdoc/clean/inline.rs | 6 +- 26 files changed, 130 insertions(+), 233 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 3cf7548e3209a..269f0ebb813ca 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -108,7 +108,7 @@ pub enum DepNode { ItemSignature(D), FieldTy(D), SizedConstraint(D), - ImplOrTraitItemIds(D), + ImplOrTraitItemDefIds(D), InherentImpls(D), // The set of impls for a given trait. Ultimately, it would be @@ -157,7 +157,7 @@ impl DepNode { ImplOrTraitItems, ItemSignature, FieldTy, - ImplOrTraitItemIds, + ImplOrTraitItemDefIds, InherentImpls, TraitImpls, ReprHints, @@ -225,7 +225,7 @@ impl DepNode { ItemSignature(ref d) => op(d).map(ItemSignature), FieldTy(ref d) => op(d).map(FieldTy), SizedConstraint(ref d) => op(d).map(SizedConstraint), - ImplOrTraitItemIds(ref d) => op(d).map(ImplOrTraitItemIds), + ImplOrTraitItemDefIds(ref d) => op(d).map(ImplOrTraitItemDefIds), InherentImpls(ref d) => op(d).map(InherentImpls), TraitImpls(ref d) => op(d).map(TraitImpls), TraitItems(ref d) => op(d).map(TraitItems), diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 52cadd76c64cb..e844ec37dc7cd 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -157,7 +157,7 @@ pub trait CrateStore<'tcx> { fn implementations_of_trait(&self, filter: Option) -> Vec; // impl info - fn impl_or_trait_items(&self, def_id: DefId) -> Vec; + fn impl_or_trait_items(&self, def_id: DefId) -> Vec; fn impl_trait_ref<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> Option>; fn impl_polarity(&self, def: DefId) -> hir::ImplPolarity; @@ -329,7 +329,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { } // impl info - fn impl_or_trait_items(&self, def_id: DefId) -> Vec + fn impl_or_trait_items(&self, def_id: DefId) -> Vec { bug!("impl_or_trait_items") } fn impl_trait_ref<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> Option> { bug!("impl_trait_ref") } diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 2c952e9f86349..70232d4f01e95 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -470,13 +470,12 @@ impl<'a, 'tcx> DeadVisitor<'a, 'tcx> { // This is done to handle the case where, for example, the static // method of a private type is used, but the type itself is never // called directly. - let impl_items = self.tcx.impl_or_trait_item_ids.borrow(); + let impl_items = self.tcx.impl_or_trait_item_def_ids.borrow(); if let Some(impl_list) = self.tcx.inherent_impls.borrow().get(&self.tcx.map.local_def_id(id)) { for impl_did in impl_list.iter() { - for item_did in impl_items.get(impl_did).unwrap().iter() { - if let Some(item_node_id) = - self.tcx.map.as_local_node_id(item_did.def_id()) { + for &item_did in &impl_items[impl_did][..] { + if let Some(item_node_id) = self.tcx.map.as_local_node_id(item_did) { if self.live_symbols.contains(&item_node_id) { return true; } diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index e2b997ed60f2d..2c768db47f11a 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -695,10 +695,9 @@ fn is_internal<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, span: Span) -> bool { fn is_staged_api<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> bool { match tcx.trait_item_of_item(id) { - Some(ty::MethodTraitItemId(trait_method_id)) - if trait_method_id != id => { - is_staged_api(tcx, trait_method_id) - } + Some(trait_method_id) if trait_method_id != id => { + is_staged_api(tcx, trait_method_id) + } _ => { *tcx.stability.borrow_mut().staged_api.entry(id.krate).or_insert_with( || tcx.sess.cstore.is_staged_api(id.krate)) diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs index 4339b1a254f20..1374719ef49c4 100644 --- a/src/librustc/traits/specialize/specialization_graph.rs +++ b/src/librustc/traits/specialize/specialization_graph.rs @@ -304,7 +304,7 @@ impl<'a, 'gcx, 'tcx> Node { /// An iterator over the items defined within a trait or impl. pub struct NodeItems<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, - items: Rc>, + items: Rc>, idx: usize } @@ -312,7 +312,7 @@ impl<'a, 'tcx> Iterator for NodeItems<'a, 'tcx> { type Item = ImplOrTraitItem<'tcx>; fn next(&mut self) -> Option> { if self.idx < self.items.len() { - let item_def_id = self.items[self.idx].def_id(); + let item_def_id = self.items[self.idx]; let items_table = self.tcx.impl_or_trait_items.borrow(); let item = items_table[&item_def_id].clone(); self.idx += 1; diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 0d6beb34c6902..1c9238646df29 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -331,7 +331,7 @@ pub struct GlobalCtxt<'tcx> { pub impl_or_trait_items: RefCell>>, /// Maps from an impl/trait def-id to a list of the def-ids of its items - pub impl_or_trait_item_ids: RefCell>>, + pub impl_or_trait_item_def_ids: RefCell>>, /// A cache for the trait_items() routine; note that the routine /// itself pushes the `TraitItems` dependency node. @@ -728,7 +728,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { rcache: RefCell::new(FnvHashMap()), tc_cache: RefCell::new(FnvHashMap()), impl_or_trait_items: RefCell::new(DepTrackingMap::new(dep_graph.clone())), - impl_or_trait_item_ids: RefCell::new(DepTrackingMap::new(dep_graph.clone())), + impl_or_trait_item_def_ids: RefCell::new(DepTrackingMap::new(dep_graph.clone())), trait_items_cache: RefCell::new(DepTrackingMap::new(dep_graph.clone())), ty_param_defs: RefCell::new(NodeMap()), normalized_cache: RefCell::new(FnvHashMap()), @@ -1396,7 +1396,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.trait_items_cache.memoize(trait_did, || { let def_ids = self.impl_or_trait_items(trait_did); Rc::new(def_ids.iter() - .map(|d| self.impl_or_trait_item(d.def_id())) + .map(|&def_id| self.impl_or_trait_item(def_id)) .collect()) }) } diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index 5e029cf98dc62..3a552a8b437d3 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -34,8 +34,7 @@ dep_map_ty! { Tcache: ItemSignature(DefId) -> Ty<'tcx> } dep_map_ty! { Generics: ItemSignature(DefId) -> &'tcx ty::Generics<'tcx> } dep_map_ty! { Predicates: ItemSignature(DefId) -> ty::GenericPredicates<'tcx> } dep_map_ty! { SuperPredicates: ItemSignature(DefId) -> ty::GenericPredicates<'tcx> } -dep_map_ty! { ImplOrTraitItemIds: ImplOrTraitItemIds(DefId) - -> Rc> } +dep_map_ty! { ImplOrTraitItemDefIds: ImplOrTraitItemDefIds(DefId) -> Rc> } dep_map_ty! { ImplTraitRefs: ItemSignature(DefId) -> Option> } dep_map_ty! { TraitDefs: ItemSignature(DefId) -> &'tcx ty::TraitDef<'tcx> } dep_map_ty! { AdtDefs: ItemSignature(DefId) -> ty::AdtDefMaster<'tcx> } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 3eb9f8593e3af..8aba6329b090b 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub use self::ImplOrTraitItemId::*; pub use self::Variance::*; pub use self::DtorKind::*; pub use self::ImplOrTraitItemContainer::*; @@ -190,18 +189,6 @@ pub enum ImplOrTraitItem<'tcx> { } impl<'tcx> ImplOrTraitItem<'tcx> { - fn id(&self) -> ImplOrTraitItemId { - match *self { - ConstTraitItem(ref associated_const) => { - ConstTraitItemId(associated_const.def_id) - } - MethodTraitItem(ref method) => MethodTraitItemId(method.def_id), - TypeTraitItem(ref associated_type) => { - TypeTraitItemId(associated_type.def_id) - } - } - } - pub fn def(&self) -> Def { match *self { ConstTraitItem(ref associated_const) => Def::AssociatedConst(associated_const.def_id), @@ -250,23 +237,6 @@ impl<'tcx> ImplOrTraitItem<'tcx> { } } -#[derive(Clone, Copy, Debug, RustcEncodable, RustcDecodable)] -pub enum ImplOrTraitItemId { - ConstTraitItemId(DefId), - MethodTraitItemId(DefId), - TypeTraitItemId(DefId), -} - -impl ImplOrTraitItemId { - pub fn def_id(&self) -> DefId { - match *self { - ConstTraitItemId(def_id) => def_id, - MethodTraitItemId(def_id) => def_id, - TypeTraitItemId(def_id) => def_id, - } - } -} - #[derive(Clone, Debug, PartialEq, Eq, Copy, RustcEncodable, RustcDecodable)] pub enum Visibility { /// Visible everywhere (including in other crates). @@ -2276,8 +2246,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } pub fn provided_trait_methods(self, id: DefId) -> Vec>> { - self.impl_or_trait_items(id).iter().filter_map(|id| { - match self.impl_or_trait_item(id.def_id()) { + self.impl_or_trait_items(id).iter().filter_map(|&def_id| { + match self.impl_or_trait_item(def_id) { MethodTraitItem(ref m) if m.has_body => Some(m.clone()), _ => None } @@ -2321,9 +2291,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { .expect("missing ImplOrTraitItem in metadata")) } - pub fn impl_or_trait_items(self, id: DefId) -> Rc> { + pub fn impl_or_trait_items(self, id: DefId) -> Rc> { lookup_locally_or_in_crate_store( - "impl_or_trait_items", id, &self.impl_or_trait_item_ids, + "impl_or_trait_items", id, &self.impl_or_trait_item_def_ids, || Rc::new(self.sess.cstore.impl_or_trait_items(id))) } @@ -2600,7 +2570,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let impl_items = self.sess.cstore.impl_or_trait_items(primitive_def_id); // Store the implementation info. - self.impl_or_trait_item_ids.borrow_mut().insert(primitive_def_id, Rc::new(impl_items)); + self.impl_or_trait_item_def_ids.borrow_mut().insert(primitive_def_id, Rc::new(impl_items)); self.populated_external_primitive_impls.borrow_mut().insert(primitive_def_id); } @@ -2627,7 +2597,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { for &impl_def_id in &inherent_impls { // Store the implementation info. let impl_items = self.sess.cstore.impl_or_trait_items(impl_def_id); - self.impl_or_trait_item_ids.borrow_mut().insert(impl_def_id, Rc::new(impl_items)); + self.impl_or_trait_item_def_ids.borrow_mut().insert(impl_def_id, Rc::new(impl_items)); } self.inherent_impls.borrow_mut().insert(type_id, inherent_impls); @@ -2669,15 +2639,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // For any methods that use a default implementation, add them to // the map. This is a bit unfortunate. - for impl_item_def_id in &impl_items { - let method_def_id = impl_item_def_id.def_id(); + for &impl_item_def_id in &impl_items { // load impl items eagerly for convenience // FIXME: we may want to load these lazily - self.impl_or_trait_item(method_def_id); + self.impl_or_trait_item(impl_item_def_id); } // Store the implementation info. - self.impl_or_trait_item_ids.borrow_mut().insert(impl_def_id, Rc::new(impl_items)); + self.impl_or_trait_item_def_ids.borrow_mut().insert(impl_def_id, Rc::new(impl_items)); } def.flags.set(def.flags.get() | TraitFlags::IMPLS_VALID); @@ -2766,19 +2735,19 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// is already that of the original trait method, then the return value is /// the same). /// Otherwise, return `None`. - pub fn trait_item_of_item(self, def_id: DefId) -> Option { + pub fn trait_item_of_item(self, def_id: DefId) -> Option { let impl_or_trait_item = match self.impl_or_trait_items.borrow().get(&def_id) { Some(m) => m.clone(), None => return None, }; match impl_or_trait_item.container() { - TraitContainer(_) => Some(impl_or_trait_item.id()), + TraitContainer(_) => Some(impl_or_trait_item.def_id()), ImplContainer(def_id) => { self.trait_id_of_impl(def_id).and_then(|trait_did| { let name = impl_or_trait_item.name(); self.trait_items(trait_did).iter() .find(|item| item.name() == name) - .map(|item| item.id()) + .map(|item| item.def_id()) }) } } diff --git a/src/librustc/ty/trait_def.rs b/src/librustc/ty/trait_def.rs index 268b2fcaa4adb..3ff2ed76e571e 100644 --- a/src/librustc/ty/trait_def.rs +++ b/src/librustc/ty/trait_def.rs @@ -15,7 +15,6 @@ use ty; use ty::fast_reject; use ty::{Ty, TyCtxt, TraitRef}; use std::cell::{Cell, RefCell}; -use syntax::ast::Name; use hir; use util::nodemap::FnvHashMap; @@ -38,10 +37,6 @@ pub struct TraitDef<'tcx> { pub trait_ref: ty::TraitRef<'tcx>, - /// A list of the associated types defined in this trait. Useful - /// for resolving `X::Foo` type markers. - pub associated_type_names: Vec, - // Impls of a trait. To allow for quicker lookup, the impls are indexed by a // simplified version of their `Self` type: impls with a simplifiable `Self` // are stored in `nonblanket_impls` keyed by it, while all other impls are @@ -82,7 +77,6 @@ impl<'a, 'gcx, 'tcx> TraitDef<'tcx> { paren_sugar: bool, generics: &'tcx ty::Generics<'tcx>, trait_ref: ty::TraitRef<'tcx>, - associated_type_names: Vec, def_path_hash: u64) -> TraitDef<'tcx> { TraitDef { @@ -90,7 +84,6 @@ impl<'a, 'gcx, 'tcx> TraitDef<'tcx> { unsafety: unsafety, generics: generics, trait_ref: trait_ref, - associated_type_names: associated_type_names, nonblanket_impls: RefCell::new(FnvHashMap()), blanket_impls: RefCell::new(vec![]), flags: Cell::new(ty::TraitFlags::NO_TRAIT_FLAGS), diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index fe3c498d184be..aa53fdd6e7e27 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -1081,16 +1081,14 @@ fn resolve_trait_associated_const<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, match selection { traits::VtableImpl(ref impl_data) => { let ac = tcx.impl_or_trait_items(impl_data.impl_def_id) - .iter().filter_map(|id| { - match *id { - ty::ConstTraitItemId(def_id) => { - Some(tcx.impl_or_trait_item(def_id)) - } + .iter().filter_map(|&def_id| { + match tcx.impl_or_trait_item(def_id) { + ty::ConstTraitItem(ic) => Some(ic), _ => None } - }).find(|ic| ic.name() == ti.name); + }).find(|ic| ic.name == ti.name); match ac { - Some(ic) => lookup_const_by_id(tcx, ic.def_id(), None), + Some(ic) => lookup_const_by_id(tcx, ic.def_id, None), None => match ti.node { hir::ConstTraitItem(ref ty, Some(ref expr)) => { Some((&*expr, tcx.ast_ty_to_prim_ty(ty))) diff --git a/src/librustc_metadata/common.rs b/src/librustc_metadata/common.rs index 94581a3fc8976..6df8c7de415a0 100644 --- a/src/librustc_metadata/common.rs +++ b/src/librustc_metadata/common.rs @@ -166,9 +166,6 @@ pub const tag_item_predicates: usize = 0x95; pub const tag_unsafety: usize = 0x9a; -pub const tag_associated_type_names: usize = 0x9b; -pub const tag_associated_type_name: usize = 0x9c; - pub const tag_polarity: usize = 0x9d; pub const tag_macro_defs: usize = 0x10e; // top-level only diff --git a/src/librustc_metadata/csearch.rs b/src/librustc_metadata/csearch.rs index 38b18fa63e3eb..c4ce7af269daa 100644 --- a/src/librustc_metadata/csearch.rs +++ b/src/librustc_metadata/csearch.rs @@ -179,10 +179,15 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { result } - fn impl_or_trait_items(&self, def_id: DefId) -> Vec { + fn impl_or_trait_items(&self, def_id: DefId) -> Vec { self.dep_graph.read(DepNode::MetaData(def_id)); - let cdata = self.get_crate_data(def_id.krate); - decoder::get_impl_or_trait_items(&cdata, def_id.index) + let mut result = vec![]; + let crate_data = self.get_crate_data(def_id.krate); + let get_crate_data = |cnum| self.get_crate_data(cnum); + decoder::each_child_of_item(&crate_data, def_id.index, get_crate_data, |def, _, _| { + result.push(def.def_id()); + }); + result } fn impl_polarity(&self, def: DefId) -> hir::ImplPolarity diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 507e6414181b8..8b87f0e718fb2 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -453,10 +453,6 @@ fn item_to_def(cdata: Cmd, item: rbml::Doc, did: DefId) -> Option { }) } -fn parse_associated_type_names(item_doc: rbml::Doc) -> Vec { - item_doc.get(tag_associated_type_names).decoder().decode() -} - pub fn get_trait_def<'a, 'tcx>(cdata: Cmd, item_id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ty::TraitDef<'tcx> @@ -464,16 +460,11 @@ pub fn get_trait_def<'a, 'tcx>(cdata: Cmd, let item_doc = cdata.lookup_item(item_id); let generics = doc_generics(item_doc, tcx, cdata); let unsafety = item_doc.get(tag_unsafety).decoder().decode(); - let associated_type_names = parse_associated_type_names(item_doc); let paren_sugar = item_doc.get(tag_paren_sugar).decoder().decode(); let trait_ref = doc_trait_ref(item_doc.get(tag_item_trait_ref), tcx, cdata); let def_path = def_path(cdata, item_id).unwrap(); - ty::TraitDef::new(unsafety, - paren_sugar, - generics, - trait_ref, - associated_type_names, + ty::TraitDef::new(unsafety, paren_sugar, generics, trait_ref, def_path.deterministic_hash(tcx)) } @@ -855,22 +846,6 @@ fn get_explicit_self<'a, 'tcx>(cdata: Cmd, item: rbml::Doc, tcx: TyCtxt<'a, 'tcx dcx.decode() } -/// Returns the def IDs of all the items in the given implementation. -pub fn get_impl_or_trait_items(cdata: Cmd, impl_id: DefIndex) - -> Vec { - let item = cdata.lookup_item(impl_id); - let mut dcx = item.get(tag_mod_children).decoder(); - dcx.cdata = Some(cdata); - dcx.seq().map(|def_id: DefId| { - match item_to_def(cdata, cdata.lookup_item(def_id.index), def_id) { - Some(Def::AssociatedConst(def_id)) => ty::ConstTraitItemId(def_id), - Some(Def::Method(def_id)) => ty::MethodTraitItemId(def_id), - Some(Def::AssociatedTy(_, def_id)) => ty::TypeTraitItemId(def_id), - def => bug!("get_impl_or_trait_items: invalid def {:?}", def) - } - }).collect() -} - pub fn get_trait_name(cdata: Cmd, id: DefIndex) -> ast::Name { let doc = cdata.lookup_item(id); item_name(doc) diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 7b4a6972d221b..326eb0fe9a3ab 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -993,8 +993,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } self.start_tag(tag_mod_children); - let items = tcx.impl_or_trait_items(def_id); - self.seq(&items[..], |_, id| id.def_id()); + tcx.impl_or_trait_items(def_id).encode(self).unwrap(); <[def::Export]>::encode(&[], self).unwrap(); self.end_tag(); @@ -1039,7 +1038,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { tcx.trait_has_default_impl(def_id).encode(self).unwrap(); self.end_tag(); - encode_associated_type_names(self, &trait_def.associated_type_names); self.encode_generics(&trait_def.generics, &trait_predicates); self.encode_predicates(&tcx.lookup_super_predicates(def_id), tag_item_super_predicates); @@ -1051,8 +1049,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { encode_deprecation(self, depr); self.start_tag(tag_mod_children); - let items = tcx.impl_or_trait_items(def_id); - self.seq(&items[..], |_, id| id.def_id()); + tcx.impl_or_trait_items(def_id).encode(self).unwrap(); <[def::Export]>::encode(&[], self).unwrap(); self.end_tag(); @@ -1151,7 +1148,6 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { None }; - let trait_item_def_id = trait_item_def_id.def_id(); self.record(trait_item_def_id, EncodeContext::encode_info_for_impl_item, (impl_id, trait_item_def_id, ast_item)); @@ -1163,8 +1159,7 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { trait_items: &[hir::TraitItem]) { // Now output the trait item info for each trait item. let r = self.tcx.impl_or_trait_items(def_id); - for (item_def_id, trait_item) in r.iter().zip(trait_items) { - let item_def_id = item_def_id.def_id(); + for (&item_def_id, trait_item) in r.iter().zip(trait_items) { assert!(item_def_id.is_local()); self.record(item_def_id, EncodeContext::encode_info_for_trait_item, @@ -1331,12 +1326,6 @@ fn encode_attributes(ecx: &mut EncodeContext, attrs: &[ast::Attribute]) { ecx.end_tag(); } -fn encode_associated_type_names(ecx: &mut EncodeContext, names: &[Name]) { - ecx.start_tag(tag_associated_type_names); - names.encode(ecx).unwrap(); - ecx.end_tag(); -} - fn encode_crate_deps(ecx: &mut EncodeContext, cstore: &cstore::CStore) { fn get_ordered_deps(cstore: &cstore::CStore) -> Vec<(CrateNum, Rc)> { diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 3df3a2decba3b..7264dcea9553e 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -432,9 +432,9 @@ impl<'b> Resolver<'b> { // info. let trait_item_def_ids = self.session.cstore.impl_or_trait_items(def_id); - for trait_item_def in &trait_item_def_ids { + for &trait_item_def in &trait_item_def_ids { let trait_item_name = - self.session.cstore.item_name(trait_item_def.def_id()); + self.session.cstore.item_name(trait_item_def); debug!("(building reduced graph for external crate) ... adding trait item \ '{}'", diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 186183a8ad4d4..aa68a873120ec 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -374,8 +374,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { let qualname = format!("{}::{}", qualname, name); let def_id = self.tcx.map.local_def_id(id); - let decl_id = self.tcx.trait_item_of_item(def_id).and_then(|new_id| { - let new_def_id = new_id.def_id(); + let decl_id = self.tcx.trait_item_of_item(def_id).and_then(|new_def_id| { if new_def_id != def_id { Some(new_def_id) } else { @@ -543,14 +542,9 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { .map(|mr| mr.def_id()) } ty::ImplContainer(def_id) => { - let impl_items = self.tcx.impl_or_trait_items(def_id); - Some(impl_items.iter() - .find(|mr| { - self.tcx.impl_or_trait_item(mr.def_id()).name() == - ti.name() - }) - .unwrap() - .def_id()) + Some(*self.tcx.impl_or_trait_items(def_id).iter().find(|&&mr| { + self.tcx.impl_or_trait_item(mr).name() == ti.name() + }).unwrap()) } } } else { diff --git a/src/librustc_trans/meth.rs b/src/librustc_trans/meth.rs index 9db5020747e1f..8540c7a99db15 100644 --- a/src/librustc_trans/meth.rs +++ b/src/librustc_trans/meth.rs @@ -235,24 +235,20 @@ pub fn get_vtable_methods<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, .iter() // Filter out non-method items. - .filter_map(|item_def_id| { - match *item_def_id { - ty::MethodTraitItemId(def_id) => Some(def_id), - _ => None, + .filter_map(|&item_def_id| { + match tcx.impl_or_trait_item(item_def_id) { + ty::MethodTraitItem(m) => Some(m), + _ => None } }) // Now produce pointers for each remaining method. If the // method could never be called from this object, just supply // null. - .map(|trait_method_def_id| { + .map(|trait_method_type| { debug!("get_vtable_methods: trait_method_def_id={:?}", - trait_method_def_id); + trait_method_type.def_id); - let trait_method_type = match tcx.impl_or_trait_item(trait_method_def_id) { - ty::MethodTraitItem(m) => m, - _ => bug!("should be a method, not other assoc item"), - }; let name = trait_method_type.name; // Some methods cannot be called on an object; skip those. @@ -266,7 +262,7 @@ pub fn get_vtable_methods<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // the method may have some early-bound lifetimes, add // regions for those - let method_substs = Substs::for_item(tcx, trait_method_def_id, + let method_substs = Substs::for_item(tcx, trait_method_type.def_id, |_, _| tcx.mk_region(ty::ReErased), |_, _| tcx.types.err); diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index 999433db24071..cad5ed4f2e651 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -248,16 +248,14 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { if let traits::VtableImpl(vtable_impl) = vtable { let name = ccx.tcx().item_name(instance.def); let ac = ccx.tcx().impl_or_trait_items(vtable_impl.impl_def_id) - .iter().filter_map(|id| { - match *id { - ty::ConstTraitItemId(def_id) => { - Some(ccx.tcx().impl_or_trait_item(def_id)) - } + .iter().filter_map(|&def_id| { + match ccx.tcx().impl_or_trait_item(def_id) { + ty::ConstTraitItem(ac) => Some(ac), _ => None } - }).find(|ic| ic.name() == name); + }).find(|ic| ic.name == name); if let Some(ac) = ac { - instance = Instance::new(ac.def_id(), vtable_impl.substs); + instance = Instance::new(ac.def_id, vtable_impl.substs); } } } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 675c863a3bf06..00c9ea3af182e 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1134,16 +1134,23 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { return tcx.types.err; } - let mut associated_types: FnvHashSet<(DefId, ast::Name)> = - traits::supertraits(tcx, principal) - .flat_map(|tr| { - let trait_def = tcx.lookup_trait_def(tr.def_id()); - trait_def.associated_type_names - .clone() - .into_iter() - .map(move |associated_type_name| (tr.def_id(), associated_type_name)) - }) - .collect(); + let mut associated_types = FnvHashSet::default(); + for tr in traits::supertraits(tcx, principal) { + if let Some(trait_id) = tcx.map.as_local_node_id(tr.def_id()) { + use collect::trait_associated_type_names; + + associated_types.extend(trait_associated_type_names(tcx, trait_id) + .map(|name| (tr.def_id(), name))) + } else { + let trait_items = tcx.impl_or_trait_items(tr.def_id()); + associated_types.extend(trait_items.iter().filter_map(|&def_id| { + match tcx.impl_or_trait_item(def_id) { + ty::TypeTraitItem(ref item) => Some(item.name), + _ => None + } + }).map(|name| (tr.def_id(), name))); + } + } for projection_bound in &projection_bounds { let pair = (projection_bound.0.projection_ty.trait_ref.def_id, diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 71219d82668e4..73caf79c9f8d1 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -368,7 +368,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { { self.tcx.impl_or_trait_items(def_id) .iter() - .map(|&did| self.tcx.impl_or_trait_item(did.def_id())) + .map(|&did| self.tcx.impl_or_trait_item(did)) .find(|m| m.name() == item_name) } } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 8d9fd523a8f52..3a854da1d4802 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1348,8 +1348,12 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> { assoc_name: ast::Name) -> bool { - let trait_def = self.tcx().lookup_trait_def(trait_def_id); - trait_def.associated_type_names.contains(&assoc_name) + self.tcx().impl_or_trait_items(trait_def_id).iter().any(|&def_id| { + match self.tcx().impl_or_trait_item(def_id) { + ty::TypeTraitItem(ref item) => item.name == assoc_name, + _ => false + } + }) } fn ty_infer(&self, _span: Span) -> Ty<'tcx> { diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index fb077d279c998..3b4c98fc71e44 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -20,8 +20,7 @@ use middle::lang_items::UnsizeTraitLangItem; use rustc::ty::subst::Subst; use rustc::ty::{self, TyCtxt, TypeFoldable}; use rustc::traits::{self, Reveal}; -use rustc::ty::{ImplOrTraitItemId, ConstTraitItemId}; -use rustc::ty::{MethodTraitItemId, TypeTraitItemId, ParameterEnvironment}; +use rustc::ty::{ParameterEnvironment}; use rustc::ty::{Ty, TyBool, TyChar, TyError}; use rustc::ty::{TyParam, TyRawPtr}; use rustc::ty::{TyRef, TyAdt, TyTrait, TyNever, TyTuple}; @@ -158,7 +157,7 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> { } } - tcx.impl_or_trait_item_ids.borrow_mut().insert(impl_did, Rc::new(impl_items)); + tcx.impl_or_trait_item_def_ids.borrow_mut().insert(impl_did, Rc::new(impl_items)); } fn add_inherent_impl(&self, base_def_id: DefId, impl_def_id: DefId) { @@ -174,22 +173,11 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> { } // Converts an implementation in the AST to a vector of items. - fn create_impl_from_item(&self, item: &Item) -> Vec { + fn create_impl_from_item(&self, item: &Item) -> Vec { match item.node { ItemImpl(.., ref impl_items) => { impl_items.iter().map(|impl_item| { - let impl_def_id = self.crate_context.tcx.map.local_def_id(impl_item.id); - match impl_item.node { - hir::ImplItemKind::Const(..) => { - ConstTraitItemId(impl_def_id) - } - hir::ImplItemKind::Method(..) => { - MethodTraitItemId(impl_def_id) - } - hir::ImplItemKind::Type(_) => { - TypeTraitItemId(impl_def_id) - } - } + self.crate_context.tcx.map.local_def_id(impl_item.id) }).collect() } _ => { @@ -210,7 +198,7 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> { tcx.populate_implementations_for_trait_if_necessary(drop_trait); let drop_trait = tcx.lookup_trait_def(drop_trait); - let impl_items = tcx.impl_or_trait_item_ids.borrow(); + let impl_items = tcx.impl_or_trait_item_def_ids.borrow(); drop_trait.for_each_impl(tcx, |impl_did| { let items = impl_items.get(&impl_did).unwrap(); @@ -223,7 +211,7 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> { let self_type = tcx.lookup_item_type(impl_did); match self_type.ty.sty { ty::TyAdt(type_def, _) => { - type_def.set_destructor(method_def_id.def_id()); + type_def.set_destructor(method_def_id); } _ => { // Destructors only work on nominal types. diff --git a/src/librustc_typeck/coherence/overlap.rs b/src/librustc_typeck/coherence/overlap.rs index 9d072491cc28b..c42b8f8840028 100644 --- a/src/librustc_typeck/coherence/overlap.rs +++ b/src/librustc_typeck/coherence/overlap.rs @@ -44,29 +44,29 @@ impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> { enum Namespace { Type, Value } fn name_and_namespace<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - item: &ty::ImplOrTraitItemId) + def_id: DefId) -> (ast::Name, Namespace) { - let name = tcx.impl_or_trait_item(item.def_id()).name(); - (name, match *item { - ty::TypeTraitItemId(..) => Namespace::Type, - ty::ConstTraitItemId(..) => Namespace::Value, - ty::MethodTraitItemId(..) => Namespace::Value, + let item = tcx.impl_or_trait_item(def_id); + (item.name(), match item { + ty::TypeTraitItem(..) => Namespace::Type, + ty::ConstTraitItem(..) => Namespace::Value, + ty::MethodTraitItem(..) => Namespace::Value, }) } - let impl_items = self.tcx.impl_or_trait_item_ids.borrow(); + let impl_items = self.tcx.impl_or_trait_item_def_ids.borrow(); - for item1 in &impl_items[&impl1][..] { + for &item1 in &impl_items[&impl1][..] { let (name, namespace) = name_and_namespace(self.tcx, item1); - for item2 in &impl_items[&impl2][..] { + for &item2 in &impl_items[&impl2][..] { if (name, namespace) == name_and_namespace(self.tcx, item2) { let msg = format!("duplicate definitions with name `{}`", name); - let node_id = self.tcx.map.as_local_node_id(item1.def_id()).unwrap(); + let node_id = self.tcx.map.as_local_node_id(item1).unwrap(); self.tcx.sess.add_lint(lint::builtin::OVERLAPPING_INHERENT_IMPLS, node_id, - self.tcx.span_of_impl(item1.def_id()).unwrap(), + self.tcx.span_of_impl(item1).unwrap(), msg); } } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index fa052bec7be3d..d67dcbb4baf0d 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -361,10 +361,15 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> { -> bool { if let Some(trait_id) = self.tcx().map.as_local_node_id(trait_def_id) { - trait_defines_associated_type_named(self.ccx, trait_id, assoc_name) + trait_associated_type_names(self.tcx(), trait_id) + .any(|name| name == assoc_name) } else { - let trait_def = self.tcx().lookup_trait_def(trait_def_id); - trait_def.associated_type_names.contains(&assoc_name) + self.tcx().impl_or_trait_items(trait_def_id).iter().any(|&def_id| { + match self.tcx().impl_or_trait_item(def_id) { + ty::TypeTraitItem(ref item) => item.name == assoc_name, + _ => false + } + }) } } @@ -926,15 +931,10 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { // Add an entry mapping let trait_item_def_ids = Rc::new(trait_items.iter().map(|trait_item| { - let def_id = ccx.tcx.map.local_def_id(trait_item.id); - match trait_item.node { - hir::ConstTraitItem(..) => ty::ConstTraitItemId(def_id), - hir::MethodTraitItem(..) => ty::MethodTraitItemId(def_id), - hir::TypeTraitItem(..) => ty::TypeTraitItemId(def_id) - } + ccx.tcx.map.local_def_id(trait_item.id) }).collect()); - tcx.impl_or_trait_item_ids.borrow_mut().insert(ccx.tcx.map.local_def_id(it.id), - trait_item_def_ids); + tcx.impl_or_trait_item_def_ids.borrow_mut().insert(ccx.tcx.map.local_def_id(it.id), + trait_item_def_ids); }, hir::ItemStruct(ref struct_def, _) | hir::ItemUnion(ref struct_def, _) => { @@ -1266,9 +1266,9 @@ fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, return def.clone(); } - let (unsafety, generics, items) = match it.node { - hir::ItemTrait(unsafety, ref generics, _, ref items) => { - (unsafety, generics, items) + let (unsafety, generics) = match it.node { + hir::ItemTrait(unsafety, ref generics, _, _) => { + (unsafety, generics) } _ => span_bug!(it.span, "trait_def_of_item invoked on non-trait"), }; @@ -1288,32 +1288,20 @@ fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let ty_generics = generics_of_def_id(ccx, def_id); let substs = mk_item_substs(&ccx.icx(generics), it.span, def_id); - let associated_type_names: Vec<_> = items.iter().filter_map(|trait_item| { - match trait_item.node { - hir::TypeTraitItem(..) => Some(trait_item.name), - _ => None, - } - }).collect(); - let def_path_hash = tcx.def_path(def_id).deterministic_hash(tcx); let trait_ref = ty::TraitRef::new(def_id, substs); - let trait_def = ty::TraitDef::new(unsafety, - paren_sugar, - ty_generics, - trait_ref, - associated_type_names, + let trait_def = ty::TraitDef::new(unsafety, paren_sugar, ty_generics, trait_ref, def_path_hash); tcx.intern_trait_def(trait_def) } -fn trait_defines_associated_type_named(ccx: &CrateCtxt, - trait_node_id: ast::NodeId, - assoc_name: ast::Name) - -> bool +pub fn trait_associated_type_names<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, + trait_node_id: ast::NodeId) + -> impl Iterator + 'a { - let item = match ccx.tcx.map.get(trait_node_id) { + let item = match tcx.map.get(trait_node_id) { hir_map::NodeItem(item) => item, _ => bug!("trait_node_id {} is not an item", trait_node_id) }; @@ -1323,10 +1311,10 @@ fn trait_defines_associated_type_named(ccx: &CrateCtxt, _ => bug!("trait_node_id {} is not a trait", trait_node_id) }; - trait_items.iter().any(|trait_item| { + trait_items.iter().filter_map(|trait_item| { match trait_item.node { - hir::TypeTraitItem(..) => trait_item.name == assoc_name, - _ => false, + hir::TypeTraitItem(..) => Some(trait_item.name), + _ => None, } }) } diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index d2e2d578fcedb..1f34cee5143c6 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -76,6 +76,7 @@ This API is completely unstable and subject to change. #![feature(box_patterns)] #![feature(box_syntax)] +#![feature(conservative_impl_trait)] #![feature(dotdot_in_tuple_patterns)] #![feature(quote)] #![feature(rustc_diagnostic_macros)] diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index e992861b77bc6..e72ea60072e08 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -368,10 +368,8 @@ pub fn build_impl<'a, 'tcx>(cx: &DocContext, let predicates = tcx.lookup_predicates(did); let trait_items = tcx.sess.cstore.impl_or_trait_items(did) .iter() - .filter_map(|did| { - let did = did.def_id(); - let impl_item = tcx.impl_or_trait_item(did); - match impl_item { + .filter_map(|&did| { + match tcx.impl_or_trait_item(did) { ty::ConstTraitItem(ref assoc_const) => { let did = assoc_const.def_id; let type_scheme = tcx.lookup_item_type(did); From d2ea3daad1372cffa5caf9f20fe36667e334662b Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Mon, 5 Sep 2016 12:18:45 +0300 Subject: [PATCH 21/39] rustc_metadata: group the tags into root tags and item tags. --- src/librustc_metadata/astencode.rs | 2 +- src/librustc_metadata/common.rs | 226 +++++++------------------ src/librustc_metadata/decoder.rs | 151 ++++++++--------- src/librustc_metadata/encoder.rs | 134 ++++++++------- src/librustc_metadata/index_builder.rs | 4 +- 5 files changed, 205 insertions(+), 312 deletions(-) diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs index f00c4b82a8518..9d4ed84993f12 100644 --- a/src/librustc_metadata/astencode.rs +++ b/src/librustc_metadata/astencode.rs @@ -33,7 +33,7 @@ use rustc_serialize::{Decodable, Encodable}; // Top-level methods. pub fn encode_inlined_item(ecx: &mut EncodeContext, ii: InlinedItemRef) { - ecx.tag(::common::tag_ast, |ecx| { + ecx.tag(::common::item_tag::ast, |ecx| { let mut visitor = IdRangeComputingVisitor::new(); match ii { InlinedItemRef::Item(_, i) => visitor.visit_item(i), diff --git a/src/librustc_metadata/common.rs b/src/librustc_metadata/common.rs index 6df8c7de415a0..04b9b7f7c6713 100644 --- a/src/librustc_metadata/common.rs +++ b/src/librustc_metadata/common.rs @@ -35,164 +35,12 @@ pub enum Family { AssociatedConst, } -// GAP 0x00...0x19 - -pub const tag_items: usize = 0x100; // top-level only - -pub const tag_paths_data_name: usize = 0x20; - -pub const tag_def_index: usize = 0x21; - -pub const tag_items_data: usize = 0x22; - -pub const tag_items_data_item: usize = 0x23; - -pub const tag_items_data_item_family: usize = 0x24; - -pub const tag_items_data_item_type: usize = 0x25; - -// GAP 0x26, 0x27 - -pub const tag_items_data_parent_item: usize = 0x28; - -pub const tag_items_data_item_is_tuple_struct_ctor: usize = 0x29; - -pub const tag_items_closure_kind: usize = 0x2a; -pub const tag_items_closure_ty: usize = 0x2b; -pub const tag_def_key: usize = 0x2c; - -// GAP 0x2d 0x34 - -pub const tag_index: usize = 0x110; // top-level only -pub const tag_xref_index: usize = 0x111; // top-level only -pub const tag_xref_data: usize = 0x112; // top-level only -pub const tag_attributes: usize = 0x101; // top-level only - -// The list of crates that this crate depends on -pub const tag_crate_deps: usize = 0x102; // top-level only -pub const tag_crate_hash: usize = 0x103; // top-level only -pub const tag_crate_crate_name: usize = 0x104; // top-level only -pub const tag_crate_disambiguator: usize = 0x113; // top-level only - -// GAP 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a - -pub const tag_item_trait_ref: usize = 0x3b; - -// discriminator value for variants -pub const tag_disr_val: usize = 0x3c; - -// GAP 0x3d, 0x3e, 0x3f, 0x40 - -pub const tag_item_fields: usize = 0x41; -// GAP 0x42 -pub const tag_item_variances: usize = 0x43; -// GAP 0x44 -pub const tag_item_trait_method_explicit_self: usize = 0x45; - -// GAP 0x46, 0x47, 0x48 - -// used to encode crate_ctxt side tables -pub const tag_ast: usize = 0x50; - -// GAP 0x51 - -pub const tag_mir: usize = 0x52; - -// GAP 0x53...0x6a - -pub const tag_item_trait_item_has_body: usize = 0x70; - -pub const tag_crate_triple: usize = 0x105; // top-level only - -pub const tag_dylib_dependency_formats: usize = 0x106; // top-level only - -pub const tag_lang_items: usize = 0x107; // top-level only - -// GAP 0x73, 0x74, 0x75 - -pub const tag_lang_items_missing: usize = 0x76; // top-level only - -// GAP 0x77 - -pub const tag_items_data_item_visibility: usize = 0x78; -pub const tag_items_data_item_inherent_impls: usize = 0x79; - -// GAP 0x7a - -// GAP 0x7c -pub const tag_mod_children: usize = 0x7b; - -// GAP 0x108 // top-level only +// NB: increment this if you change the format of metadata such that +// rustc_version can't be found. +pub const metadata_encoding_version : &'static [u8] = &[b'r', b'u', b's', b't', 0, 0, 0, 2]; // GAP 0x7c - // GAP 0x108 -pub const tag_impls: usize = 0x109; // top-level only - -// GAP 0x7d, 0x7e, 0x7f, 0x80, 0x81 - -pub const tag_native_libraries: usize = 0x10a; // top-level only - -// GAP 0x82, 0x83, 0x84 - -pub const tag_plugin_registrar_fn: usize = 0x10b; // top-level only - -pub const tag_method_argument_names: usize = 0x85; - -// GAP 0x86 - -pub const tag_reachable_ids: usize = 0x10c; // top-level only - -// GAP 0x87 - -pub const tag_items_data_item_stability: usize = 0x88; - -pub const tag_items_data_item_repr: usize = 0x89; - -// GAP 0x10d // top-level only - -// GAP 0x8a - -pub const tag_items_data_item_struct_ctor: usize = 0x8b; -pub const tag_attribute_is_sugared_doc: usize = 0x8c; -// GAP 0x8d -pub const tag_items_data_region: usize = 0x8e; - -pub const tag_item_generics: usize = 0x8f; -// GAP 0x90, 0x91, 0x92, 0x93, 0x94 - -pub const tag_item_predicates: usize = 0x95; -// GAP 0x96, 0x97, 0x98, 0x99 - -pub const tag_unsafety: usize = 0x9a; - -pub const tag_polarity: usize = 0x9d; - -pub const tag_macro_defs: usize = 0x10e; // top-level only - -// GAP 0x9e, 0x9f - -pub const tag_paren_sugar: usize = 0xa0; - -pub const tag_codemap: usize = 0xa1; - -// GAP 0xa2 - -pub const tag_item_super_predicates: usize = 0xa3; - -pub const tag_defaulted_trait: usize = 0xa4; - -pub const tag_impl_coerce_unsized_kind: usize = 0xa5; - -pub const tag_items_data_item_constness: usize = 0xa6; - -pub const tag_items_data_item_deprecation: usize = 0xa7; - -pub const tag_items_data_item_defaultness: usize = 0xa8; - -pub const tag_items_data_parent_impl: usize = 0xa9; - -pub const tag_rustc_version: usize = 0x10f; pub fn rustc_version() -> String { format!( "rustc {}", @@ -200,13 +48,69 @@ pub fn rustc_version() -> String { ) } -pub const tag_panic_strategy: usize = 0x114; - -pub const tag_macro_derive_registrar: usize = 0x115; +pub mod root_tag { + pub const rustc_version: usize = 0x10f; + pub const crate_deps: usize = 0x102; + pub const crate_hash: usize = 0x103; + pub const crate_crate_name: usize = 0x104; + pub const crate_disambiguator: usize = 0x113; + pub const items: usize = 0x100; + pub const index: usize = 0x110; + pub const xref_index: usize = 0x111; + pub const xref_data: usize = 0x112; + pub const crate_triple: usize = 0x105; + pub const dylib_dependency_formats: usize = 0x106; + pub const lang_items: usize = 0x107; + pub const lang_items_missing: usize = 0x76; + pub const impls: usize = 0x109; + pub const native_libraries: usize = 0x10a; + pub const plugin_registrar_fn: usize = 0x10b; + pub const panic_strategy: usize = 0x114; + pub const macro_derive_registrar: usize = 0x115; + pub const reachable_ids: usize = 0x10c; + pub const macro_defs: usize = 0x10e; + pub const codemap: usize = 0xa1; +} -// NB: increment this if you change the format of metadata such that -// rustc_version can't be found. -pub const metadata_encoding_version : &'static [u8] = &[b'r', b'u', b's', b't', 0, 0, 0, 2]; +pub mod item_tag { + pub const name: usize = 0x20; + pub const def_index: usize = 0x21; + pub const family: usize = 0x24; + pub const ty: usize = 0x25; + pub const parent_item: usize = 0x28; + pub const is_tuple_struct_ctor: usize = 0x29; + pub const closure_kind: usize = 0x2a; + pub const closure_ty: usize = 0x2b; + pub const def_key: usize = 0x2c; + pub const attributes: usize = 0x101; + pub const trait_ref: usize = 0x3b; + pub const disr_val: usize = 0x3c; + pub const fields: usize = 0x41; + pub const variances: usize = 0x43; + pub const trait_method_explicit_self: usize = 0x45; + pub const ast: usize = 0x50; + pub const mir: usize = 0x52; + pub const trait_item_has_body: usize = 0x70; + pub const visibility: usize = 0x78; + pub const inherent_impls: usize = 0x79; + pub const children: usize = 0x7b; + pub const method_argument_names: usize = 0x85; + pub const stability: usize = 0x88; + pub const repr: usize = 0x89; + pub const struct_ctor: usize = 0x8b; + pub const generics: usize = 0x8f; + pub const predicates: usize = 0x95; + pub const unsafety: usize = 0x9a; + pub const polarity: usize = 0x9d; + pub const paren_sugar: usize = 0xa0; + pub const super_predicates: usize = 0xa3; + pub const defaulted_trait: usize = 0xa4; + pub const impl_coerce_unsized_kind: usize = 0xa5; + pub const constness: usize = 0xa6; + pub const deprecation: usize = 0xa7; + pub const defaultness: usize = 0xa8; + pub const parent_impl: usize = 0xa9; +} /// The shorthand encoding of `Ty` uses `TypeVariants`' variant `usize` /// and is offset by this value so it never matches a real variant. diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 8b87f0e718fb2..662236be0f0d2 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -324,53 +324,53 @@ impl CrateMetadata { } pub fn load_index(data: &[u8]) -> index::Index { - index::Index::from_rbml(rbml::Doc::new(data).get(tag_index)) + index::Index::from_rbml(rbml::Doc::new(data).get(root_tag::index)) } pub fn crate_rustc_version(data: &[u8]) -> Option { let doc = rbml::Doc::new(data); - reader::maybe_get_doc(doc, tag_rustc_version).map(|s| { + reader::maybe_get_doc(doc, root_tag::rustc_version).map(|s| { str::from_utf8(&s.data[s.start..s.end]).unwrap().to_string() }) } pub fn load_xrefs(data: &[u8]) -> index::DenseIndex { - let index = rbml::Doc::new(data).get(tag_xref_index); + let index = rbml::Doc::new(data).get(root_tag::xref_index); index::DenseIndex::from_buf(index.data, index.start, index.end) } // Go through each item in the metadata and create a map from that // item's def-key to the item's DefIndex. pub fn load_key_map(data: &[u8]) -> FnvHashMap { - rbml::Doc::new(data).get(tag_items).get(tag_items_data).children().map(|item_doc| { + rbml::Doc::new(data).get(root_tag::items).children().map(|item_doc| { // load def-key from item let key = item_def_key(item_doc); // load def-index from item - (key, item_doc.get(tag_def_index).decoder().decode()) + (key, item_doc.get(item_tag::def_index).decoder().decode()) }).collect() } fn item_family(item: rbml::Doc) -> Family { - item.get(tag_items_data_item_family).decoder().decode() + item.get(item_tag::family).decoder().decode() } fn item_visibility(item: rbml::Doc) -> ty::Visibility { - match reader::maybe_get_doc(item, tag_items_data_item_visibility) { + match reader::maybe_get_doc(item, item_tag::visibility) { None => ty::Visibility::Public, Some(visibility_doc) => visibility_doc.decoder().decode() } } fn item_defaultness(item: rbml::Doc) -> hir::Defaultness { - match reader::maybe_get_doc(item, tag_items_data_item_defaultness) { + match reader::maybe_get_doc(item, item_tag::defaultness) { None => hir::Defaultness::Default, // should occur only for default impls on traits Some(defaultness_doc) => defaultness_doc.decoder().decode() } } fn item_parent_item(cdata: Cmd, d: rbml::Doc) -> Option { - reader::maybe_get_doc(d, tag_items_data_parent_item).map(|did| { + reader::maybe_get_doc(d, item_tag::parent_item).map(|did| { let mut dcx = did.decoder(); dcx.cdata = Some(cdata); dcx.decode() @@ -378,7 +378,7 @@ fn item_parent_item(cdata: Cmd, d: rbml::Doc) -> Option { } fn item_require_parent_item(cdata: Cmd, d: rbml::Doc) -> DefId { - let mut dcx = d.get(tag_items_data_parent_item).decoder(); + let mut dcx = d.get(item_tag::parent_item).decoder(); dcx.cdata = Some(cdata); dcx.decode() } @@ -386,17 +386,17 @@ fn item_require_parent_item(cdata: Cmd, d: rbml::Doc) -> DefId { fn item_def_id(d: rbml::Doc, cdata: Cmd) -> DefId { DefId { krate: cdata.cnum, - index: d.get(tag_def_index).decoder().decode() + index: d.get(item_tag::def_index).decoder().decode() } } fn doc_type<'a, 'tcx>(doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>, cdata: Cmd) -> Ty<'tcx> { - maybe_doc_type(doc, tcx, cdata).expect("missing tag_items_data_item_type") + maybe_doc_type(doc, tcx, cdata).expect("missing item_tag::ty") } fn maybe_doc_type<'a, 'tcx>(doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>, cdata: Cmd) -> Option> { - reader::maybe_get_doc(doc, tag_items_data_item_type).map(|tp| { + reader::maybe_get_doc(doc, item_tag::ty).map(|tp| { let mut dcx = tp.decoder(); dcx.tcx = Some(tcx); dcx.cdata = Some(cdata); @@ -417,7 +417,7 @@ fn item_name(item: rbml::Doc) -> ast::Name { } fn maybe_item_name(item: rbml::Doc) -> Option { - reader::maybe_get_doc(item, tag_paths_data_name).map(|name| { + reader::maybe_get_doc(item, item_tag::name).map(|name| { name.decoder().decode() }) } @@ -459,9 +459,9 @@ pub fn get_trait_def<'a, 'tcx>(cdata: Cmd, { let item_doc = cdata.lookup_item(item_id); let generics = doc_generics(item_doc, tcx, cdata); - let unsafety = item_doc.get(tag_unsafety).decoder().decode(); - let paren_sugar = item_doc.get(tag_paren_sugar).decoder().decode(); - let trait_ref = doc_trait_ref(item_doc.get(tag_item_trait_ref), tcx, cdata); + let unsafety = item_doc.get(item_tag::unsafety).decoder().decode(); + let paren_sugar = item_doc.get(item_tag::paren_sugar).decoder().decode(); + let trait_ref = doc_trait_ref(item_doc.get(item_tag::trait_ref), tcx, cdata); let def_path = def_path(cdata, item_id).unwrap(); ty::TraitDef::new(unsafety, paren_sugar, generics, trait_ref, @@ -481,12 +481,12 @@ pub fn get_adt_def<'a, 'tcx>(cdata: Cmd, } } fn get_enum_variants<'tcx>(cdata: Cmd, doc: rbml::Doc) -> Vec> { - let mut dcx = doc.get(tag_mod_children).decoder(); + let mut dcx = doc.get(item_tag::children).decoder(); dcx.cdata = Some(cdata); dcx.seq().map(|did: DefId| { let item = cdata.lookup_item(did.index); - let disr = item.get(tag_disr_val).decoder().decode(); + let disr = item.get(item_tag::disr_val).decoder().decode(); ty::VariantDefData { did: did, name: item_name(item), @@ -497,7 +497,7 @@ pub fn get_adt_def<'a, 'tcx>(cdata: Cmd, }).collect() } fn get_variant_fields<'tcx>(cdata: Cmd, doc: rbml::Doc) -> Vec> { - let mut dcx = doc.get(tag_item_fields).decoder(); + let mut dcx = doc.get(item_tag::fields).decoder(); dcx.cdata = Some(cdata); dcx.seq().map(|did: DefId| { @@ -531,7 +531,7 @@ pub fn get_adt_def<'a, 'tcx>(cdata: Cmd, } Struct(..) => { // Use separate constructor id for unit/tuple structs and reuse did for braced structs. - ctor_did = reader::maybe_get_doc(doc, tag_items_data_item_struct_ctor).map(|ctor_doc| { + ctor_did = reader::maybe_get_doc(doc, item_tag::struct_ctor).map(|ctor_doc| { let mut dcx = ctor_doc.decoder(); dcx.cdata = Some(cdata); dcx.decode() @@ -595,7 +595,7 @@ pub fn get_predicates<'a, 'tcx>(cdata: Cmd, -> ty::GenericPredicates<'tcx> { let item_doc = cdata.lookup_item(item_id); - doc_predicates(item_doc, tcx, cdata, tag_item_predicates) + doc_predicates(item_doc, tcx, cdata, item_tag::predicates) } pub fn get_super_predicates<'a, 'tcx>(cdata: Cmd, @@ -604,7 +604,7 @@ pub fn get_super_predicates<'a, 'tcx>(cdata: Cmd, -> ty::GenericPredicates<'tcx> { let item_doc = cdata.lookup_item(item_id); - doc_predicates(item_doc, tcx, cdata, tag_item_super_predicates) + doc_predicates(item_doc, tcx, cdata, item_tag::super_predicates) } pub fn get_generics<'a, 'tcx>(cdata: Cmd, @@ -625,14 +625,14 @@ pub fn get_type<'a, 'tcx>(cdata: Cmd, id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) pub fn get_stability(cdata: Cmd, id: DefIndex) -> Option { let item = cdata.lookup_item(id); - reader::maybe_get_doc(item, tag_items_data_item_stability).map(|doc| { + reader::maybe_get_doc(item, item_tag::stability).map(|doc| { doc.decoder().decode() }) } pub fn get_deprecation(cdata: Cmd, id: DefIndex) -> Option { let item = cdata.lookup_item(id); - reader::maybe_get_doc(item, tag_items_data_item_deprecation).map(|doc| { + reader::maybe_get_doc(item, item_tag::deprecation).map(|doc| { doc.decoder().decode() }) } @@ -643,7 +643,7 @@ pub fn get_visibility(cdata: Cmd, id: DefIndex) -> ty::Visibility { pub fn get_parent_impl(cdata: Cmd, id: DefIndex) -> Option { let item = cdata.lookup_item(id); - reader::maybe_get_doc(item, tag_items_data_parent_impl).map(|doc| { + reader::maybe_get_doc(item, item_tag::parent_impl).map(|doc| { let mut dcx = doc.decoder(); dcx.cdata = Some(cdata); dcx.decode() @@ -652,13 +652,13 @@ pub fn get_parent_impl(cdata: Cmd, id: DefIndex) -> Option { pub fn get_repr_attrs(cdata: Cmd, id: DefIndex) -> Vec { let item = cdata.lookup_item(id); - reader::maybe_get_doc(item, tag_items_data_item_repr).map_or(vec![], |doc| { + reader::maybe_get_doc(item, item_tag::repr).map_or(vec![], |doc| { doc.decoder().decode() }) } pub fn get_impl_polarity(cdata: Cmd, id: DefIndex) -> hir::ImplPolarity { - cdata.lookup_item(id).get(tag_polarity).decoder().decode() + cdata.lookup_item(id).get(item_tag::polarity).decoder().decode() } pub fn get_custom_coerce_unsized_kind( @@ -667,7 +667,7 @@ pub fn get_custom_coerce_unsized_kind( -> Option { let item_doc = cdata.lookup_item(id); - reader::maybe_get_doc(item_doc, tag_impl_coerce_unsized_kind).map(|kind_doc| { + reader::maybe_get_doc(item_doc, item_tag::impl_coerce_unsized_kind).map(|kind_doc| { kind_doc.decoder().decode() }) } @@ -678,14 +678,14 @@ pub fn get_impl_trait<'a, 'tcx>(cdata: Cmd, -> Option> { let item_doc = cdata.lookup_item(id); - reader::maybe_get_doc(item_doc, tag_item_trait_ref).map(|tp| { + reader::maybe_get_doc(item_doc, item_tag::trait_ref).map(|tp| { doc_trait_ref(tp, tcx, cdata) }) } /// Iterates over the language items in the given crate. pub fn get_lang_items(cdata: Cmd) -> Vec<(DefIndex, usize)> { - rbml::Doc::new(cdata.data()).get(tag_lang_items).decoder().decode() + rbml::Doc::new(cdata.data()).get(root_tag::lang_items).decoder().decode() } @@ -702,7 +702,7 @@ pub fn each_child_of_item(cdata: Cmd, id: DefIndex, Some(item_doc) => item_doc, }; - let mut dcx = match reader::maybe_get_doc(item_doc, tag_mod_children) { + let mut dcx = match reader::maybe_get_doc(item_doc, item_tag::children) { Some(doc) => doc.decoder(), None => return }; @@ -782,7 +782,7 @@ pub fn maybe_get_item_ast<'a, 'tcx>(cdata: Cmd, tcx: TyCtxt<'a, 'tcx, 'tcx>, id: }; let mut parent_def_path = def_path(cdata, id).unwrap(); parent_def_path.data.pop(); - if let Some(ast_doc) = reader::maybe_get_doc(item_doc, tag_ast as usize) { + if let Some(ast_doc) = reader::maybe_get_doc(item_doc, item_tag::ast as usize) { let ii = decode_inlined_item(cdata, tcx, parent_def_path, @@ -800,7 +800,7 @@ pub fn maybe_get_item_ast<'a, 'tcx>(cdata: Cmd, tcx: TyCtxt<'a, 'tcx, 'tcx>, id: let mut grandparent_def_path = parent_def_path; grandparent_def_path.data.pop(); let parent_doc = cdata.lookup_item(parent_did.index); - if let Some(ast_doc) = reader::maybe_get_doc(parent_doc, tag_ast as usize) { + if let Some(ast_doc) = reader::maybe_get_doc(parent_doc, item_tag::ast as usize) { let ii = decode_inlined_item(cdata, tcx, grandparent_def_path, @@ -817,7 +817,7 @@ pub fn maybe_get_item_ast<'a, 'tcx>(cdata: Cmd, tcx: TyCtxt<'a, 'tcx, 'tcx>, id: pub fn is_item_mir_available<'tcx>(cdata: Cmd, id: DefIndex) -> bool { if let Some(item_doc) = cdata.get_item(id) { - return reader::maybe_get_doc(item_doc, tag_mir as usize).is_some(); + return reader::maybe_get_doc(item_doc, item_tag::mir as usize).is_some(); } false @@ -829,7 +829,7 @@ pub fn maybe_get_item_mir<'a, 'tcx>(cdata: Cmd, -> Option> { let item_doc = cdata.lookup_item(id); - reader::maybe_get_doc(item_doc, tag_mir).map(|mir_doc| { + reader::maybe_get_doc(item_doc, item_tag::mir).map(|mir_doc| { let mut dcx = mir_doc.decoder(); dcx.tcx = Some(tcx); dcx.cdata = Some(cdata); @@ -839,7 +839,7 @@ pub fn maybe_get_item_mir<'a, 'tcx>(cdata: Cmd, fn get_explicit_self<'a, 'tcx>(cdata: Cmd, item: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ty::ExplicitSelfCategory<'tcx> { - let mut dcx = item.get(tag_item_trait_method_explicit_self).decoder(); + let mut dcx = item.get(item_tag::trait_method_explicit_self).decoder(); dcx.cdata = Some(cdata); dcx.tcx = Some(tcx); @@ -881,12 +881,12 @@ pub fn get_impl_or_trait_item<'a, 'tcx>(cdata: Cmd, id: DefIndex, tcx: TyCtxt<'a defaultness: defaultness, def_id: def_id, container: container, - has_value: item_doc.get(tag_item_trait_item_has_body).decoder().decode(), + has_value: item_doc.get(item_tag::trait_item_has_body).decoder().decode(), })) } Family::Method => { let generics = doc_generics(item_doc, tcx, cdata); - let predicates = doc_predicates(item_doc, tcx, cdata, tag_item_predicates); + let predicates = doc_predicates(item_doc, tcx, cdata, item_tag::predicates); let ity = tcx.lookup_item_type(def_id).ty; let fty = match ity.sty { ty::TyFnDef(.., fty) => fty, @@ -904,7 +904,7 @@ pub fn get_impl_or_trait_item<'a, 'tcx>(cdata: Cmd, id: DefIndex, tcx: TyCtxt<'a explicit_self: explicit_self, vis: vis, defaultness: defaultness, - has_body: item_doc.get(tag_item_trait_item_has_body).decoder().decode(), + has_body: item_doc.get(item_tag::trait_item_has_body).decoder().decode(), def_id: def_id, container: container, })) @@ -926,13 +926,13 @@ pub fn get_impl_or_trait_item<'a, 'tcx>(cdata: Cmd, id: DefIndex, tcx: TyCtxt<'a pub fn get_item_variances(cdata: Cmd, id: DefIndex) -> Vec { let item_doc = cdata.lookup_item(id); - item_doc.get(tag_item_variances).decoder().decode() + item_doc.get(item_tag::variances).decoder().decode() } pub fn get_struct_ctor_def_id(cdata: Cmd, node_id: DefIndex) -> Option { let item = cdata.lookup_item(node_id); - reader::maybe_get_doc(item, tag_items_data_item_struct_ctor).map(|ctor_doc| { + reader::maybe_get_doc(item, item_tag::struct_ctor).map(|ctor_doc| { let mut dcx = ctor_doc.decoder(); dcx.cdata = Some(cdata); dcx.decode() @@ -946,7 +946,7 @@ pub fn get_tuple_struct_definition_if_ctor(cdata: Cmd, -> Option { let item = cdata.lookup_item(node_id); - reader::maybe_get_doc(item, tag_items_data_item_is_tuple_struct_ctor).and_then(|doc| { + reader::maybe_get_doc(item, item_tag::is_tuple_struct_ctor).and_then(|doc| { if doc.decoder().decode() { Some(item_require_parent_item(cdata, item)) } else { @@ -968,7 +968,7 @@ pub fn get_item_attrs(cdata: Cmd, } pub fn get_struct_field_names(cdata: Cmd, id: DefIndex) -> Vec { - let mut dcx = cdata.lookup_item(id).get(tag_item_fields).decoder(); + let mut dcx = cdata.lookup_item(id).get(item_tag::fields).decoder(); dcx.cdata = Some(cdata); dcx.seq().map(|did: DefId| { @@ -977,7 +977,7 @@ pub fn get_struct_field_names(cdata: Cmd, id: DefIndex) -> Vec { } fn get_attributes(md: rbml::Doc) -> Vec { - reader::maybe_get_doc(md, tag_attributes).map_or(vec![], |attrs_doc| { + reader::maybe_get_doc(md, item_tag::attributes).map_or(vec![], |attrs_doc| { let mut attrs = attrs_doc.decoder().decode::>(); // Need new unique IDs: old thread-local IDs won't map to new threads. @@ -998,7 +998,7 @@ pub struct CrateDep { } pub fn get_crate_deps(data: &[u8]) -> Vec { - let dcx = rbml::Doc::new(data).get(tag_crate_deps).decoder(); + let dcx = rbml::Doc::new(data).get(root_tag::crate_deps).decoder(); dcx.seq().enumerate().map(|(crate_num, (name, hash, explicitly_linked))| { CrateDep { @@ -1021,29 +1021,29 @@ fn list_crate_deps(data: &[u8], out: &mut io::Write) -> io::Result<()> { pub fn maybe_get_crate_hash(data: &[u8]) -> Option { let cratedoc = rbml::Doc::new(data); - reader::maybe_get_doc(cratedoc, tag_crate_hash).map(|doc| { + reader::maybe_get_doc(cratedoc, root_tag::crate_hash).map(|doc| { doc.decoder().decode() }) } pub fn get_crate_hash(data: &[u8]) -> Svh { - rbml::Doc::new(data).get(tag_crate_hash).decoder().decode() + rbml::Doc::new(data).get(root_tag::crate_hash).decoder().decode() } pub fn maybe_get_crate_name(data: &[u8]) -> Option { let cratedoc = rbml::Doc::new(data); - reader::maybe_get_doc(cratedoc, tag_crate_crate_name).map(|doc| { + reader::maybe_get_doc(cratedoc, root_tag::crate_crate_name).map(|doc| { doc.decoder().decode() }) } pub fn get_crate_disambiguator(data: &[u8]) -> String { - rbml::Doc::new(data).get(tag_crate_disambiguator).decoder().decode() + rbml::Doc::new(data).get(root_tag::crate_disambiguator).decoder().decode() } pub fn get_crate_triple(data: &[u8]) -> Option { let cratedoc = rbml::Doc::new(data); - let triple_doc = reader::maybe_get_doc(cratedoc, tag_crate_triple); + let triple_doc = reader::maybe_get_doc(cratedoc, root_tag::crate_triple); triple_doc.map(|s| s.decoder().decode()) } @@ -1073,7 +1073,7 @@ pub fn each_inherent_implementation_for_type(cdata: Cmd, where F: FnMut(DefId), { let item_doc = cdata.lookup_item(id); - let mut dcx = item_doc.get(tag_items_data_item_inherent_impls).decoder(); + let mut dcx = item_doc.get(item_tag::inherent_impls).decoder(); dcx.cdata = Some(cdata); for impl_def_id in dcx.seq() { @@ -1095,7 +1095,7 @@ pub fn each_implementation_for_trait(cdata: Cmd, }; // FIXME(eddyb) Make this O(1) instead of O(n). - for trait_doc in rbml::Doc::new(cdata.data()).get(tag_impls).children() { + for trait_doc in rbml::Doc::new(cdata.data()).get(root_tag::impls).children() { let mut dcx = trait_doc.decoder(); dcx.cdata = Some(cdata); @@ -1128,18 +1128,18 @@ pub fn get_trait_of_item(cdata: Cmd, id: DefIndex) -> Option { pub fn get_native_libraries(cdata: Cmd) -> Vec<(cstore::NativeLibraryKind, String)> { - rbml::Doc::new(cdata.data()).get(tag_native_libraries).decoder().decode() + rbml::Doc::new(cdata.data()).get(root_tag::native_libraries).decoder().decode() } pub fn get_plugin_registrar_fn(data: &[u8]) -> Option { - reader::maybe_get_doc(rbml::Doc::new(data), tag_plugin_registrar_fn) + reader::maybe_get_doc(rbml::Doc::new(data), root_tag::plugin_registrar_fn) .map(|doc| doc.decoder().decode()) } pub fn each_exported_macro(data: &[u8], mut f: F) where F: FnMut(ast::Name, Vec, Span, String) -> bool, { - let dcx = rbml::Doc::new(data).get(tag_macro_defs).decoder(); + let dcx = rbml::Doc::new(data).get(root_tag::macro_defs).decoder(); for (name, attrs, span, body) in dcx.seq() { if !f(name, attrs, span, body) { break; @@ -1148,14 +1148,14 @@ pub fn each_exported_macro(data: &[u8], mut f: F) where } pub fn get_derive_registrar_fn(data: &[u8]) -> Option { - reader::maybe_get_doc(rbml::Doc::new(data), tag_macro_derive_registrar) + reader::maybe_get_doc(rbml::Doc::new(data), root_tag::macro_derive_registrar) .map(|doc| doc.decoder().decode()) } pub fn get_dylib_dependency_formats(cdata: Cmd) -> Vec<(CrateNum, LinkagePreference)> { - let dcx = rbml::Doc::new(cdata.data()).get(tag_dylib_dependency_formats).decoder(); + let dcx = rbml::Doc::new(cdata.data()).get(root_tag::dylib_dependency_formats).decoder(); dcx.seq::>().enumerate().flat_map(|(i, link)| { let cnum = CrateNum::new(i + 1); @@ -1164,19 +1164,19 @@ pub fn get_dylib_dependency_formats(cdata: Cmd) } pub fn get_missing_lang_items(cdata: Cmd) -> Vec { - rbml::Doc::new(cdata.data()).get(tag_lang_items_missing).decoder().decode() + rbml::Doc::new(cdata.data()).get(root_tag::lang_items_missing).decoder().decode() } pub fn get_method_arg_names(cdata: Cmd, id: DefIndex) -> Vec { let method_doc = cdata.lookup_item(id); - match reader::maybe_get_doc(method_doc, tag_method_argument_names) { + match reader::maybe_get_doc(method_doc, item_tag::method_argument_names) { Some(args_doc) => args_doc.decoder().decode(), None => vec![], } } pub fn get_reachable_ids(cdata: Cmd) -> Vec { - let dcx = rbml::Doc::new(cdata.data()).get(tag_reachable_ids).decoder(); + let dcx = rbml::Doc::new(cdata.data()).get(root_tag::reachable_ids).decoder(); dcx.seq().map(|index| { DefId { @@ -1187,7 +1187,7 @@ pub fn get_reachable_ids(cdata: Cmd) -> Vec { } pub fn is_const_fn(cdata: Cmd, id: DefIndex) -> bool { - match reader::maybe_get_doc(cdata.lookup_item(id), tag_items_data_item_constness) { + match reader::maybe_get_doc(cdata.lookup_item(id), item_tag::constness) { None => false, Some(doc) => { match doc.decoder().decode() { @@ -1235,7 +1235,7 @@ fn doc_generics<'a, 'tcx>(base_doc: rbml::Doc, cdata: Cmd) -> &'tcx ty::Generics<'tcx> { - let mut dcx = base_doc.get(tag_item_generics).decoder(); + let mut dcx = base_doc.get(item_tag::generics).decoder(); dcx.tcx = Some(tcx); dcx.cdata = Some(cdata); tcx.alloc_generics(dcx.decode()) @@ -1268,7 +1268,7 @@ fn doc_predicates<'a, 'tcx>(base_doc: rbml::Doc, } pub fn is_defaulted_trait(cdata: Cmd, trait_id: DefIndex) -> bool { - cdata.lookup_item(trait_id).get(tag_defaulted_trait).decoder().decode() + cdata.lookup_item(trait_id).get(item_tag::defaulted_trait).decoder().decode() } pub fn is_default_impl(cdata: Cmd, impl_id: DefIndex) -> bool { @@ -1276,17 +1276,17 @@ pub fn is_default_impl(cdata: Cmd, impl_id: DefIndex) -> bool { } pub fn get_imported_filemaps(metadata: &[u8]) -> Vec { - rbml::Doc::new(metadata).get(tag_codemap).decoder().decode() + rbml::Doc::new(metadata).get(root_tag::codemap).decoder().decode() } pub fn closure_kind(cdata: Cmd, closure_id: DefIndex) -> ty::ClosureKind { - cdata.lookup_item(closure_id).get(tag_items_closure_kind).decoder().decode() + cdata.lookup_item(closure_id).get(item_tag::closure_kind).decoder().decode() } pub fn closure_ty<'a, 'tcx>(cdata: Cmd, closure_id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ty::ClosureTy<'tcx> { let closure_doc = cdata.lookup_item(closure_id); - let closure_ty_doc = closure_doc.get(tag_items_closure_ty); + let closure_ty_doc = closure_doc.get(item_tag::closure_ty); let mut dcx = closure_ty_doc.decoder(); dcx.tcx = Some(tcx); dcx.cdata = Some(cdata); @@ -1300,18 +1300,9 @@ pub fn def_key(cdata: Cmd, id: DefIndex) -> hir_map::DefKey { } fn item_def_key(item_doc: rbml::Doc) -> hir_map::DefKey { - match reader::maybe_get_doc(item_doc, tag_def_key) { - Some(def_key_doc) => { - let simple_key = def_key_doc.decoder().decode(); - let name = maybe_item_name(item_doc).map(|name| name.as_str()); - def_key::recover_def_key(simple_key, name) - } - None => { - bug!("failed to find block with tag {:?} for item with family {:?}", - tag_def_key, - item_family(item_doc)) - } - } + let simple_key = item_doc.get(item_tag::def_key).decoder().decode(); + let name = maybe_item_name(item_doc).map(|name| name.as_str()); + def_key::recover_def_key(simple_key, name) } // Returns the path leading to the thing with this `id`. Note that @@ -1327,5 +1318,5 @@ pub fn def_path(cdata: Cmd, id: DefIndex) -> Option { } pub fn get_panic_strategy(data: &[u8]) -> PanicStrategy { - rbml::Doc::new(data).get(tag_panic_strategy).decoder().decode() + rbml::Doc::new(data).get(root_tag::panic_strategy).decoder().decode() } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 326eb0fe9a3ab..1e4c61e0b2e10 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -169,21 +169,21 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } fn encode_name(ecx: &mut EncodeContext, name: Name) { - ecx.start_tag(tag_paths_data_name); + ecx.start_tag(item_tag::name); name.encode(ecx).unwrap(); ecx.end_tag(); } fn encode_def_id(ecx: &mut EncodeContext, def_id: DefId) { assert!(def_id.is_local()); - ecx.start_tag(tag_def_index); + ecx.start_tag(item_tag::def_index); def_id.index.encode(ecx).unwrap(); ecx.end_tag(); } fn encode_def_key(ecx: &mut EncodeContext, key: DefKey) { let simple_key = def_key::simplify_def_key(key); - ecx.start_tag(tag_def_key); + ecx.start_tag(item_tag::def_key); simple_key.encode(ecx); ecx.end_tag(); } @@ -206,14 +206,14 @@ fn encode_trait_ref<'a, 'tcx>(ecx: &mut EncodeContext<'a, 'tcx>, // Item info table encoding fn encode_family(ecx: &mut EncodeContext, f: Family) { - ecx.start_tag(tag_items_data_item_family); + ecx.start_tag(item_tag::family); f.encode(ecx).unwrap(); ecx.end_tag(); } fn encode_item_variances(ecx: &mut EncodeContext, id: NodeId) { let v = ecx.tcx.item_variances(ecx.tcx.map.local_def_id(id)); - ecx.start_tag(tag_item_variances); + ecx.start_tag(item_tag::variances); v.encode(ecx); ecx.end_tag(); } @@ -233,27 +233,27 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } fn encode_type(&mut self, typ: Ty<'tcx>) { - self.start_tag(tag_items_data_item_type); + self.start_tag(item_tag::ty); typ.encode(self).unwrap(); self.end_tag(); } fn encode_disr_val(&mut self, disr_val: ty::Disr) { - self.start_tag(tag_disr_val); + self.start_tag(item_tag::disr_val); disr_val.to_u64_unchecked().encode(self).unwrap(); self.end_tag(); } fn encode_parent_item(&mut self, id: DefId) { - self.start_tag(tag_items_data_parent_item); + self.start_tag(item_tag::parent_item); id.encode(self).unwrap(); self.end_tag(); } fn encode_variant_fields(&mut self, variant: ty::VariantDef) { - self.start_tag(tag_item_fields); + self.start_tag(item_tag::fields); self.seq(&variant.fields, |_, f| f.did); self.end_tag(); } @@ -321,7 +321,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { debug!("(encoding info for module) encoding info for module ID {}", id); // Encode info about all the module children. - self.start_tag(tag_mod_children); + self.start_tag(item_tag::children); self.seq(&md.item_ids, |_, item_id| { tcx.map.local_def_id(item_id.id) }); @@ -358,7 +358,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } else { ty::Visibility::PrivateExternal }; - self.start_tag(tag_items_data_item_visibility); + self.start_tag(item_tag::visibility); vis.encode(self).unwrap(); self.end_tag(); } @@ -381,13 +381,13 @@ impl HasVisibility for ty::Visibility { } fn encode_constness(ecx: &mut EncodeContext, constness: hir::Constness) { - ecx.start_tag(tag_items_data_item_constness); + ecx.start_tag(item_tag::constness); constness.encode(ecx).unwrap(); ecx.end_tag(); } fn encode_defaultness(ecx: &mut EncodeContext, defaultness: hir::Defaultness) { - ecx.start_tag(tag_items_data_item_defaultness); + ecx.start_tag(item_tag::defaultness); defaultness.encode(ecx).unwrap(); ecx.end_tag(); } @@ -463,7 +463,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { // definition, but without this there is no way for them // to tell that they actually have a ctor rather than a // normal function - self.start_tag(tag_items_data_item_is_tuple_struct_ctor); + self.start_tag(item_tag::is_tuple_struct_ctor); true.encode(self).unwrap(); self.end_tag(); } @@ -472,10 +472,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { generics: &ty::Generics<'tcx>, predicates: &ty::GenericPredicates<'tcx>) { - self.start_tag(tag_item_generics); + self.start_tag(item_tag::generics); generics.encode(self).unwrap(); self.end_tag(); - self.encode_predicates(predicates, tag_item_predicates); + self.encode_predicates(predicates, item_tag::predicates); } fn encode_predicates(&mut self, @@ -495,7 +495,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.encode_generics(&method_ty.generics, &method_ty.predicates); self.encode_visibility(method_ty.vis); - self.start_tag(tag_item_trait_method_explicit_self); + self.start_tag(item_tag::trait_method_explicit_self); method_ty.explicit_self.encode(self).unwrap(); self.end_tag(); @@ -541,7 +541,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { encode_attributes(self, &trait_item.attrs); match trait_item.node { hir::ConstTraitItem(_, ref default) => { - self.start_tag(tag_item_trait_item_has_body); + self.start_tag(item_tag::trait_item_has_body); default.is_some().encode(self).unwrap(); self.end_tag(); @@ -550,7 +550,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.encode_mir(item_def_id); } hir::MethodTraitItem(ref sig, ref body) => { - self.start_tag(tag_item_trait_item_has_body); + self.start_tag(item_tag::trait_item_has_body); body.is_some().encode(self).unwrap(); self.end_tag(); @@ -600,7 +600,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.encode_parent_item(tcx.map.local_def_id(parent_id)); - self.start_tag(tag_item_trait_item_has_body); + self.start_tag(item_tag::trait_item_has_body); true.encode(self).unwrap(); self.end_tag(); @@ -632,7 +632,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.encode_method_ty_fields(m); self.encode_parent_item(tcx.map.local_def_id(parent_id)); - self.start_tag(tag_item_trait_item_has_body); + self.start_tag(item_tag::trait_item_has_body); true.encode(self).unwrap(); self.end_tag(); @@ -697,7 +697,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn encode_method_argument_names(&mut self, decl: &hir::FnDecl) { - self.start_tag(tag_method_argument_names); + self.start_tag(item_tag::method_argument_names); self.seq(&decl.inputs, |_, arg| { if let PatKind::Binding(_, ref path1, _) = arg.pat.node { @@ -717,14 +717,14 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { repr_attrs.extend(attr::find_repr_attrs(self.tcx.sess.diagnostic(), attr)); } - self.start_tag(tag_items_data_item_repr); + self.start_tag(item_tag::repr); repr_attrs.encode(self); self.end_tag(); } fn encode_mir(&mut self, def_id: DefId) { if let Some(mir) = self.mir_map.map.get(&def_id) { - self.start_tag(tag_mir as usize); + self.start_tag(item_tag::mir as usize); mir.encode(self); self.end_tag(); } @@ -734,7 +734,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { // Encodes the inherent implementations of a structure, enumeration, or trait. fn encode_inherent_implementations(ecx: &mut EncodeContext, def_id: DefId) { - ecx.start_tag(tag_items_data_item_inherent_impls); + ecx.start_tag(item_tag::inherent_impls); match ecx.tcx.inherent_impls.borrow().get(&def_id) { None => <[DefId]>::encode(&[], ecx).unwrap(), Some(implementations) => implementations.encode(ecx).unwrap() @@ -744,7 +744,7 @@ fn encode_inherent_implementations(ecx: &mut EncodeContext, fn encode_stability(ecx: &mut EncodeContext, stab_opt: Option<&attr::Stability>) { stab_opt.map(|stab| { - ecx.start_tag(tag_items_data_item_stability); + ecx.start_tag(item_tag::stability); stab.encode(ecx).unwrap(); ecx.end_tag(); }); @@ -752,7 +752,7 @@ fn encode_stability(ecx: &mut EncodeContext, stab_opt: Option<&attr::Stability>) fn encode_deprecation(ecx: &mut EncodeContext, depr_opt: Option) { depr_opt.map(|depr| { - ecx.start_tag(tag_items_data_item_deprecation); + ecx.start_tag(item_tag::deprecation); depr.encode(ecx).unwrap(); ecx.end_tag(); }); @@ -772,7 +772,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let mut sorted_xrefs: Vec<_> = xrefs.into_iter().collect(); sorted_xrefs.sort_by_key(|&(_, id)| id); - self.start_tag(tag_xref_data); + self.start_tag(root_tag::xref_data); for (xref, id) in sorted_xrefs.into_iter() { xref_positions[id as usize] = self.mark_stable_position() as u32; match xref { @@ -782,7 +782,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.mark_stable_position(); self.end_tag(); - self.start_tag(tag_xref_index); + self.start_tag(root_tag::xref_index); index::write_dense_index(xref_positions, &mut self.opaque.cursor); self.end_tag(); } @@ -857,7 +857,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { encode_name(self, item.name); // Encode all the items in self module. - self.start_tag(tag_mod_children); + self.start_tag(item_tag::children); self.seq(&fm.items, |_, foreign_item| { tcx.map.local_def_id(foreign_item.id) }); @@ -886,7 +886,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { encode_attributes(self, &item.attrs); self.encode_repr_attrs(&item.attrs); - self.start_tag(tag_mod_children); + self.start_tag(item_tag::children); self.seq(&enum_definition.variants, |_, v| { tcx.map.local_def_id(v.node.data.id()) }); @@ -928,7 +928,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { if !struct_def.is_struct() { let ctor_did = tcx.map.local_def_id(struct_def.id()); - self.start_tag(tag_items_data_item_struct_ctor); + self.start_tag(item_tag::struct_ctor); ctor_did.encode(self).unwrap(); self.end_tag(); } @@ -966,7 +966,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { encode_name(self, item.name); let trait_ref = tcx.impl_trait_ref(tcx.map.local_def_id(item.id)).unwrap(); - encode_trait_ref(self, trait_ref, tag_item_trait_ref); + encode_trait_ref(self, trait_ref, item_tag::trait_ref); } hir::ItemImpl(_, polarity, ..) => { encode_def_id_and_key(self, def_id); @@ -975,7 +975,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { encode_name(self, item.name); encode_attributes(self, &item.attrs); - self.start_tag(tag_polarity); + self.start_tag(item_tag::polarity); polarity.encode(self).unwrap(); self.end_tag(); @@ -985,21 +985,21 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { .get(&tcx.map.local_def_id(item.id)) { Some(&kind) => { - self.start_tag(tag_impl_coerce_unsized_kind); + self.start_tag(item_tag::impl_coerce_unsized_kind); kind.encode(self); self.end_tag(); } None => {} } - self.start_tag(tag_mod_children); + self.start_tag(item_tag::children); tcx.impl_or_trait_items(def_id).encode(self).unwrap(); <[def::Export]>::encode(&[], self).unwrap(); self.end_tag(); let did = tcx.map.local_def_id(item.id); if let Some(trait_ref) = tcx.impl_trait_ref(did) { - encode_trait_ref(self, trait_ref, tag_item_trait_ref); + encode_trait_ref(self, trait_ref, item_tag::trait_ref); let trait_def = tcx.lookup_trait_def(trait_ref.def_id); let parent = trait_def.ancestors(did) @@ -1011,7 +1011,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { _ => None, }); parent.map(|parent| { - self.start_tag(tag_items_data_parent_impl); + self.start_tag(item_tag::parent_impl); parent.encode(self).unwrap(); self.end_tag(); }); @@ -1026,29 +1026,29 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let trait_def = tcx.lookup_trait_def(def_id); let trait_predicates = tcx.lookup_predicates(def_id); - self.start_tag(tag_unsafety); + self.start_tag(item_tag::unsafety); trait_def.unsafety.encode(self).unwrap(); self.end_tag(); - self.start_tag(tag_paren_sugar); + self.start_tag(item_tag::paren_sugar); trait_def.paren_sugar.encode(self).unwrap(); self.end_tag(); - self.start_tag(tag_defaulted_trait); + self.start_tag(item_tag::defaulted_trait); tcx.trait_has_default_impl(def_id).encode(self).unwrap(); self.end_tag(); self.encode_generics(&trait_def.generics, &trait_predicates); self.encode_predicates(&tcx.lookup_super_predicates(def_id), - tag_item_super_predicates); - encode_trait_ref(self, trait_def.trait_ref, tag_item_trait_ref); + item_tag::super_predicates); + encode_trait_ref(self, trait_def.trait_ref, item_tag::trait_ref); encode_name(self, item.name); encode_attributes(self, &item.attrs); self.encode_visibility(vis); encode_stability(self, stab); encode_deprecation(self, depr); - self.start_tag(tag_mod_children); + self.start_tag(item_tag::children); tcx.impl_or_trait_items(def_id).encode(self).unwrap(); <[def::Export]>::encode(&[], self).unwrap(); self.end_tag(); @@ -1276,11 +1276,11 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { encode_def_id_and_key(self, def_id); encode_name(self, syntax::parse::token::intern("")); - self.start_tag(tag_items_closure_ty); + self.start_tag(item_tag::closure_ty); tcx.tables.borrow().closure_tys[&def_id].encode(self).unwrap(); self.end_tag(); - self.start_tag(tag_items_closure_kind); + self.start_tag(item_tag::closure_kind); tcx.closure_kind(def_id).encode(self).unwrap(); self.end_tag(); @@ -1292,7 +1292,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn encode_info_for_items(ecx: &mut EncodeContext) -> IndexData { let krate = ecx.tcx.map.krate(); - ecx.start_tag(tag_items_data); + ecx.start_tag(root_tag::items); let items = { let mut index = IndexBuilder::new(ecx); @@ -1315,13 +1315,13 @@ fn encode_info_for_items(ecx: &mut EncodeContext) -> IndexData { } fn encode_item_index(ecx: &mut EncodeContext, index: IndexData) { - ecx.start_tag(tag_index); + ecx.start_tag(root_tag::index); index.write_index(&mut ecx.opaque.cursor); ecx.end_tag(); } fn encode_attributes(ecx: &mut EncodeContext, attrs: &[ast::Attribute]) { - ecx.start_tag(tag_attributes); + ecx.start_tag(item_tag::attributes); attrs.encode(ecx).unwrap(); ecx.end_tag(); } @@ -1352,7 +1352,7 @@ fn encode_crate_deps(ecx: &mut EncodeContext, cstore: &cstore::CStore) { // the assumption that they are numbered 1 to n. // FIXME (#2166): This is not nearly enough to support correct versioning // but is enough to get transitive crate dependencies working. - ecx.start_tag(tag_crate_deps); + ecx.start_tag(root_tag::crate_deps); ecx.seq(&get_ordered_deps(cstore), |_, &(_, ref dep)| { (dep.name(), decoder::get_crate_hash(dep.data()), dep.explicitly_linked.get()) @@ -1376,11 +1376,11 @@ fn encode_lang_items(ecx: &mut EncodeContext) { let count = lang_items().count(); let mut lang_items = lang_items(); - ecx.start_tag(tag_lang_items); + ecx.start_tag(root_tag::lang_items); ecx.seq(0..count, |_, _| lang_items.next().unwrap()); ecx.end_tag(); - ecx.start_tag(tag_lang_items_missing); + ecx.start_tag(root_tag::lang_items_missing); tcx.lang_items.missing.encode(ecx).unwrap(); ecx.end_tag(); } @@ -1401,7 +1401,7 @@ fn encode_native_libraries(ecx: &mut EncodeContext) { let count = libs().count(); let mut libs = libs(); - ecx.start_tag(tag_native_libraries); + ecx.start_tag(root_tag::native_libraries); ecx.seq(0..count, |_, _| libs.next().unwrap()); ecx.end_tag(); } @@ -1410,7 +1410,7 @@ fn encode_plugin_registrar_fn(ecx: &mut EncodeContext) { match ecx.tcx.sess.plugin_registrar_fn.get() { Some(id) => { let def_id = ecx.tcx.map.local_def_id(id); - ecx.start_tag(tag_plugin_registrar_fn); + ecx.start_tag(root_tag::plugin_registrar_fn); def_id.index.encode(ecx).unwrap(); ecx.end_tag(); } @@ -1434,7 +1434,7 @@ fn encode_codemap(ecx: &mut EncodeContext) { let count = filemaps().count(); let mut filemaps = filemaps(); - ecx.start_tag(tag_codemap); + ecx.start_tag(root_tag::codemap); ecx.seq(0..count, |_, _| filemaps.next().unwrap()); ecx.end_tag(); } @@ -1442,7 +1442,7 @@ fn encode_codemap(ecx: &mut EncodeContext) { /// Serialize the text of the exported macros fn encode_macro_defs(ecx: &mut EncodeContext) { let tcx = ecx.tcx; - ecx.start_tag(tag_macro_defs); + ecx.start_tag(root_tag::macro_defs); ecx.seq(&tcx.map.krate().exported_macros, |_, def| { let body = ::syntax::print::pprust::tts_to_string(&def.body); (def.name, &def.attrs, def.span, body) @@ -1453,7 +1453,7 @@ fn encode_macro_defs(ecx: &mut EncodeContext) { let id = ecx.tcx.sess.derive_registrar_fn.get().unwrap(); let did = ecx.tcx.map.local_def_id(id); - ecx.start_tag(tag_macro_derive_registrar); + ecx.start_tag(root_tag::macro_derive_registrar); did.index.encode(ecx).unwrap(); ecx.end_tag(); } @@ -1485,7 +1485,7 @@ fn encode_impls(ecx: &mut EncodeContext) { }; ecx.tcx.map.krate().visit_all_items(&mut visitor); - ecx.start_tag(tag_impls); + ecx.start_tag(root_tag::impls); for (trait_def_id, trait_impls) in visitor.impls { // FIXME(eddyb) Avoid wrapping the entries in docs. ecx.start_tag(0); @@ -1503,7 +1503,7 @@ fn encode_impls(ecx: &mut EncodeContext) { // symbol associated with them (they weren't translated) or if they're an FFI // definition (as that's not defined in this crate). fn encode_reachable(ecx: &mut EncodeContext) { - ecx.start_tag(tag_reachable_ids); + ecx.start_tag(root_tag::reachable_ids); let reachable = ecx.reachable; ecx.seq(reachable, |ecx, &id| ecx.tcx.map.local_def_id(id).index); @@ -1512,7 +1512,7 @@ fn encode_reachable(ecx: &mut EncodeContext) { } fn encode_dylib_dependency_formats(ecx: &mut EncodeContext) { - ecx.start_tag(tag_dylib_dependency_formats); + ecx.start_tag(root_tag::dylib_dependency_formats); match ecx.tcx.sess.dependency_formats.borrow().get(&config::CrateTypeDylib) { Some(arr) => { ecx.seq(arr, |_, slot| { @@ -1596,30 +1596,30 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } fn encode_metadata_inner(ecx: &mut EncodeContext) { - ecx.wr_tagged_str(tag_rustc_version, &rustc_version()); + ecx.wr_tagged_str(root_tag::rustc_version, &rustc_version()); let tcx = ecx.tcx; let link_meta = ecx.link_meta; - ecx.start_tag(tag_crate_crate_name); + ecx.start_tag(root_tag::crate_crate_name); link_meta.crate_name.encode(ecx).unwrap(); ecx.end_tag(); - ecx.start_tag(tag_crate_triple); + ecx.start_tag(root_tag::crate_triple); tcx.sess.opts.target_triple.encode(ecx).unwrap(); ecx.end_tag(); - ecx.start_tag(tag_crate_hash); + ecx.start_tag(root_tag::crate_hash); link_meta.crate_hash.encode(ecx).unwrap(); ecx.end_tag(); - ecx.start_tag(tag_crate_disambiguator); + ecx.start_tag(root_tag::crate_disambiguator); tcx.sess.local_crate_disambiguator().encode(ecx).unwrap(); ecx.end_tag(); encode_dylib_dependency_formats(ecx); - ecx.start_tag(tag_panic_strategy); + ecx.start_tag(root_tag::panic_strategy); ecx.tcx.sess.opts.cg.panic.encode(ecx); ecx.end_tag(); @@ -1663,11 +1663,9 @@ fn encode_metadata_inner(ecx: &mut EncodeContext) { let reachable_bytes = ecx.position() - i; // Encode and index the items. - ecx.start_tag(tag_items); i = ecx.position(); let items = encode_info_for_items(ecx); let item_bytes = ecx.position() - i; - ecx.end_tag(); i = ecx.position(); encode_item_index(ecx, items); diff --git a/src/librustc_metadata/index_builder.rs b/src/librustc_metadata/index_builder.rs index 2cfa6f8d5d115..372577e21f116 100644 --- a/src/librustc_metadata/index_builder.rs +++ b/src/librustc_metadata/index_builder.rs @@ -55,7 +55,6 @@ //! give a callback fn, rather than taking a closure: it allows us to //! easily control precisely what data is given to that fn. -use common::tag_items_data_item; use encoder::EncodeContext; use index::IndexData; use rustc::dep_graph::DepNode; @@ -120,7 +119,8 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { let position = self.ecx.mark_stable_position(); self.items.record(id, position); let _task = self.tcx.dep_graph.in_task(DepNode::MetaData(id)); - self.ecx.start_tag(tag_items_data_item).unwrap(); + // FIXME(eddyb) Avoid wrapping the entries in docs. + self.ecx.start_tag(0).unwrap(); data.read(self.tcx); op(&mut self.ecx, data); self.ecx.end_tag().unwrap(); From 6742b239ac0e1fad2e3981b6201d5789b7298554 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Mon, 5 Sep 2016 13:38:26 +0300 Subject: [PATCH 22/39] rustc_metadata: remove all unnecessary tables from astencode. --- src/librustc_metadata/astencode.rs | 82 +----------------------------- 1 file changed, 2 insertions(+), 80 deletions(-) diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs index 9d4ed84993f12..c687353d437c1 100644 --- a/src/librustc_metadata/astencode.rs +++ b/src/librustc_metadata/astencode.rs @@ -19,10 +19,9 @@ use decoder::DecodeContext; use encoder::EncodeContext; use middle::cstore::{InlinedItem, InlinedItemRef}; -use rustc::ty::adjustment; use rustc::hir::def; use rustc::hir::def_id::DefId; -use rustc::ty::{self, TyCtxt}; +use rustc::ty::TyCtxt; use syntax::ast; @@ -128,12 +127,8 @@ enum Table { Def, NodeType, ItemSubsts, - Freevars, - MethodMap, Adjustment, - UpvarCaptureMap, - ConstQualif, - CastKind + ConstQualif } fn encode_side_tables_for_id(ecx: &mut EncodeContext, id: ast::NodeId) { @@ -156,60 +151,11 @@ fn encode_side_tables_for_id(ecx: &mut EncodeContext, id: ast::NodeId) { item_substs.substs.encode(ecx).unwrap(); } - if let Some(fv) = tcx.freevars.borrow().get(&id) { - ecx.entry(Table::Freevars, id); - fv.encode(ecx).unwrap(); - - for freevar in fv { - ecx.entry(Table::UpvarCaptureMap, id); - let def_id = freevar.def.def_id(); - let var_id = tcx.map.as_local_node_id(def_id).unwrap(); - let upvar_id = ty::UpvarId { - var_id: var_id, - closure_expr_id: id - }; - let upvar_capture = tcx.tables - .borrow() - .upvar_capture_map - .get(&upvar_id) - .unwrap() - .clone(); - var_id.encode(ecx).unwrap(); - upvar_capture.encode(ecx).unwrap(); - } - } - - let method_call = ty::MethodCall::expr(id); - if let Some(method) = tcx.tables.borrow().method_map.get(&method_call) { - ecx.entry(Table::MethodMap, id); - method_call.autoderef.encode(ecx).unwrap(); - method.encode(ecx).unwrap(); - } - if let Some(adjustment) = tcx.tables.borrow().adjustments.get(&id) { - match *adjustment { - adjustment::AdjustDerefRef(ref adj) => { - for autoderef in 0..adj.autoderefs { - let method_call = ty::MethodCall::autoderef(id, autoderef as u32); - if let Some(method) = tcx.tables.borrow().method_map.get(&method_call) { - ecx.entry(Table::MethodMap, id); - method_call.autoderef.encode(ecx).unwrap(); - method.encode(ecx).unwrap(); - } - } - } - _ => {} - } - ecx.entry(Table::Adjustment, id); adjustment.encode(ecx).unwrap(); } - if let Some(cast_kind) = tcx.cast_kinds.borrow().get(&id) { - ecx.entry(Table::CastKind, id); - cast_kind.encode(ecx).unwrap(); - } - if let Some(qualif) = tcx.const_qualif_map.borrow().get(&id) { ecx.entry(Table::ConstQualif, id); qualif.encode(ecx).unwrap(); @@ -234,34 +180,10 @@ fn decode_side_tables(dcx: &mut DecodeContext, ast_doc: rbml::Doc) { let item_substs = Decodable::decode(dcx).unwrap(); dcx.tcx().tables.borrow_mut().item_substs.insert(id, item_substs); } - Table::Freevars => { - let fv_info = Decodable::decode(dcx).unwrap(); - dcx.tcx().freevars.borrow_mut().insert(id, fv_info); - } - Table::UpvarCaptureMap => { - let upvar_id = ty::UpvarId { - var_id: Decodable::decode(dcx).unwrap(), - closure_expr_id: id - }; - let ub = Decodable::decode(dcx).unwrap(); - dcx.tcx().tables.borrow_mut().upvar_capture_map.insert(upvar_id, ub); - } - Table::MethodMap => { - let method_call = ty::MethodCall { - expr_id: id, - autoderef: Decodable::decode(dcx).unwrap() - }; - let method = Decodable::decode(dcx).unwrap(); - dcx.tcx().tables.borrow_mut().method_map.insert(method_call, method); - } Table::Adjustment => { let adj = Decodable::decode(dcx).unwrap(); dcx.tcx().tables.borrow_mut().adjustments.insert(id, adj); } - Table::CastKind => { - let cast_kind = Decodable::decode(dcx).unwrap(); - dcx.tcx().cast_kinds.borrow_mut().insert(id, cast_kind); - } Table::ConstQualif => { let qualif = Decodable::decode(dcx).unwrap(); dcx.tcx().const_qualif_map.borrow_mut().insert(id, qualif); From ef4352fba6f0a93b55eeaf2c2cdf10f0e0401719 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Thu, 8 Sep 2016 19:05:50 +0300 Subject: [PATCH 23/39] rustc_metadata: group information into less tags. --- src/librustc/hir/def.rs | 10 +- src/librustc/hir/pat_util.rs | 2 +- src/librustc/middle/cstore.rs | 11 +- src/librustc/middle/dead.rs | 6 +- src/librustc/middle/expr_use_visitor.rs | 3 +- src/librustc/middle/mem_categorization.rs | 13 +- src/librustc/ty/context.rs | 10 +- src/librustc/ty/item_path.rs | 2 +- src/librustc/ty/mod.rs | 18 +- src/librustc_const_eval/check_match.rs | 6 +- src/librustc_const_eval/eval.rs | 11 +- .../calculate_svh/svh_visitor.rs | 1 - src/librustc_metadata/astencode.rs | 2 +- src/librustc_metadata/common.rs | 176 ++- src/librustc_metadata/creader.rs | 65 +- src/librustc_metadata/csearch.rs | 92 +- src/librustc_metadata/cstore.rs | 20 +- src/librustc_metadata/decoder.rs | 685 ++++------- src/librustc_metadata/def_key.rs | 110 -- src/librustc_metadata/encoder.rs | 1069 ++++++----------- src/librustc_metadata/index.rs | 12 + src/librustc_metadata/lib.rs | 20 +- src/librustc_metadata/loader.rs | 33 +- src/librustc_mir/hair/cx/expr.rs | 8 +- src/librustc_mir/hair/cx/pattern.rs | 3 +- src/librustc_passes/static_recursion.rs | 14 +- src/librustc_privacy/lib.rs | 18 +- src/librustc_resolve/build_reduced_graph.rs | 26 +- src/librustc_resolve/lib.rs | 4 +- src/librustc_save_analysis/dump_visitor.rs | 3 +- src/librustc_typeck/astconv.rs | 5 +- src/librustc_typeck/check/mod.rs | 11 +- src/librustdoc/clean/inline.rs | 18 +- src/librustdoc/clean/mod.rs | 10 +- src/librustdoc/visit_lib.rs | 8 +- 35 files changed, 972 insertions(+), 1533 deletions(-) delete mode 100644 src/librustc_metadata/def_key.rs diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs index fddf09c990566..dec8ea8a29c39 100644 --- a/src/librustc/hir/def.rs +++ b/src/librustc/hir/def.rs @@ -18,15 +18,14 @@ pub enum Def { Fn(DefId), SelfTy(Option /* trait */, Option /* impl */), Mod(DefId), - ForeignMod(DefId), Static(DefId, bool /* is_mutbl */), Const(DefId), AssociatedConst(DefId), Local(DefId), - Variant(DefId /* enum */, DefId /* variant */), + Variant(DefId), Enum(DefId), TyAlias(DefId), - AssociatedTy(DefId /* trait */, DefId), + AssociatedTy(DefId), Trait(DefId), PrimTy(hir::PrimTy), TyParam(DefId), @@ -101,8 +100,8 @@ pub struct Export { impl Def { pub fn def_id(&self) -> DefId { match *self { - Def::Fn(id) | Def::Mod(id) | Def::ForeignMod(id) | Def::Static(id, _) | - Def::Variant(_, id) | Def::Enum(id) | Def::TyAlias(id) | Def::AssociatedTy(_, id) | + Def::Fn(id) | Def::Mod(id) | Def::Static(id, _) | + Def::Variant(id) | Def::Enum(id) | Def::TyAlias(id) | Def::AssociatedTy(id) | Def::TyParam(id) | Def::Struct(id) | Def::Union(id) | Def::Trait(id) | Def::Method(id) | Def::Const(id) | Def::AssociatedConst(id) | Def::Local(id) | Def::Upvar(id, ..) => { @@ -122,7 +121,6 @@ impl Def { match *self { Def::Fn(..) => "function", Def::Mod(..) => "module", - Def::ForeignMod(..) => "foreign module", Def::Static(..) => "static", Def::Variant(..) => "variant", Def::Enum(..) => "enum", diff --git a/src/librustc/hir/pat_util.rs b/src/librustc/hir/pat_util.rs index a63bf14cb0238..dec41fdfc3b50 100644 --- a/src/librustc/hir/pat_util.rs +++ b/src/librustc/hir/pat_util.rs @@ -174,7 +174,7 @@ pub fn necessary_variants(dm: &DefMap, pat: &hir::Pat) -> Vec { PatKind::Path(..) | PatKind::Struct(..) => { match dm.get(&p.id) { - Some(&PathResolution { base_def: Def::Variant(_, id), .. }) => { + Some(&PathResolution { base_def: Def::Variant(id), .. }) => { variants.push(id); } _ => () diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index e844ec37dc7cd..87fdc858cf0f5 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -135,11 +135,9 @@ pub trait CrateStore<'tcx> { fn closure_ty<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> ty::ClosureTy<'tcx>; fn item_variances(&self, def: DefId) -> Vec; - fn repr_attrs(&self, def: DefId) -> Vec; fn item_type<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> Ty<'tcx>; fn visible_parent_map<'a>(&'a self) -> ::std::cell::RefMut<'a, DefIdMap>; - fn item_name(&self, def: DefId) -> ast::Name; fn opt_item_name(&self, def: DefId) -> Option; fn item_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> ty::GenericPredicates<'tcx>; @@ -150,7 +148,7 @@ pub trait CrateStore<'tcx> { fn item_attrs(&self, def_id: DefId) -> Vec; fn trait_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)-> ty::TraitDef<'tcx>; fn adt_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> ty::AdtDefMaster<'tcx>; - fn method_arg_names(&self, did: DefId) -> Vec; + fn fn_arg_names(&self, did: DefId) -> Vec; fn inherent_implementations_for_type(&self, def_id: DefId) -> Vec; // trait info @@ -211,7 +209,6 @@ pub trait CrateStore<'tcx> { fn def_key(&self, def: DefId) -> hir_map::DefKey; fn relative_def_path(&self, def: DefId) -> Option; fn struct_ctor_def_id(&self, struct_def_id: DefId) -> Option; - fn tuple_struct_definition_if_ctor(&self, did: DefId) -> Option; fn struct_field_names(&self, def: DefId) -> Vec; fn item_children(&self, did: DefId) -> Vec; @@ -297,13 +294,11 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { fn closure_ty<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> ty::ClosureTy<'tcx> { bug!("closure_ty") } fn item_variances(&self, def: DefId) -> Vec { bug!("item_variances") } - fn repr_attrs(&self, def: DefId) -> Vec { bug!("repr_attrs") } fn item_type<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> Ty<'tcx> { bug!("item_type") } fn visible_parent_map<'a>(&'a self) -> ::std::cell::RefMut<'a, DefIdMap> { bug!("visible_parent_map") } - fn item_name(&self, def: DefId) -> ast::Name { bug!("item_name") } fn opt_item_name(&self, def: DefId) -> Option { bug!("opt_item_name") } fn item_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> ty::GenericPredicates<'tcx> { bug!("item_predicates") } @@ -316,7 +311,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { { bug!("trait_def") } fn adt_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> ty::AdtDefMaster<'tcx> { bug!("adt_def") } - fn method_arg_names(&self, did: DefId) -> Vec { bug!("method_arg_names") } + fn fn_arg_names(&self, did: DefId) -> Vec { bug!("fn_arg_names") } fn inherent_implementations_for_type(&self, def_id: DefId) -> Vec { vec![] } // trait info @@ -393,8 +388,6 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { } fn struct_ctor_def_id(&self, struct_def_id: DefId) -> Option { bug!("struct_ctor_def_id") } - fn tuple_struct_definition_if_ctor(&self, did: DefId) -> Option - { bug!("tuple_struct_definition_if_ctor") } fn struct_field_names(&self, def: DefId) -> Vec { bug!("struct_field_names") } fn item_children(&self, did: DefId) -> Vec { bug!("item_children") } diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 70232d4f01e95..30a0c6a9dc939 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -108,8 +108,10 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { _ if self.ignore_non_const_paths => (), Def::PrimTy(_) => (), Def::SelfTy(..) => (), - Def::Variant(enum_id, variant_id) => { - self.check_def_id(enum_id); + Def::Variant(variant_id) => { + if let Some(enum_id) = self.tcx.parent_def_id(variant_id) { + self.check_def_id(enum_id); + } if !self.ignore_variant_stack.contains(&variant_id) { self.check_def_id(variant_id); } diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index ec3fe3903179a..5b5c3da8f05b2 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -1003,7 +1003,8 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { // the leaves of the pattern tree structure. return_if_err!(mc.cat_pattern(cmt_discr, pat, |mc, cmt_pat, pat| { match tcx.expect_def_or_none(pat.id) { - Some(Def::Variant(enum_did, variant_did)) => { + Some(Def::Variant(variant_did)) => { + let enum_did = tcx.parent_def_id(variant_did).unwrap(); let downcast_cmt = if tcx.lookup_adt_def(enum_did).is_univariant() { cmt_pat } else { diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 26cc6007ed07a..340a5ac8f87b7 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -529,7 +529,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { Ok(self.cat_rvalue_node(id, span, expr_ty)) } - Def::Mod(_) | Def::ForeignMod(_) | + Def::Mod(_) | Def::Trait(_) | Def::Enum(..) | Def::TyAlias(..) | Def::PrimTy(_) | Def::TyParam(..) | Def::Label(_) | Def::SelfTy(..) | @@ -1077,18 +1077,23 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { // alone) because PatKind::Struct can also refer to variants. let cmt = match self.tcx().expect_def_or_none(pat.id) { Some(Def::Err) => return Err(()), - Some(Def::Variant(enum_did, variant_did)) + Some(Def::Variant(variant_did)) => { // univariant enums do not need downcasts - if !self.tcx().lookup_adt_def(enum_did).is_univariant() => { + let enum_did = self.tcx().parent_def_id(variant_did).unwrap(); + if !self.tcx().lookup_adt_def(enum_did).is_univariant() { self.cat_downcast(pat, cmt.clone(), cmt.ty, variant_did) + } else { + cmt } + } _ => cmt }; match pat.node { PatKind::TupleStruct(_, ref subpats, ddpos) => { let expected_len = match self.tcx().expect_def(pat.id) { - Def::Variant(enum_def, def_id) => { + Def::Variant(def_id) => { + let enum_def = self.tcx().parent_def_id(def_id).unwrap(); self.tcx().lookup_adt_def(enum_def).variant_with_id(def_id).fields.len() } Def::Struct(..) => { diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 1c9238646df29..0faf6750abd97 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1404,13 +1404,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// Obtain the representation annotation for a struct definition. pub fn lookup_repr_hints(self, did: DefId) -> Rc> { self.repr_hint_cache.memoize(did, || { - Rc::new(if did.is_local() { - self.get_attrs(did).iter().flat_map(|meta| { - attr::find_repr_attrs(self.sess.diagnostic(), meta).into_iter() - }).collect() - } else { - self.sess.cstore.repr_attrs(did) - }) + Rc::new(self.get_attrs(did).iter().flat_map(|meta| { + attr::find_repr_attrs(self.sess.diagnostic(), meta).into_iter() + }).collect()) }) } } diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index e4247a60b15ec..5f121b568c3af 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -303,7 +303,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// Returns the def-id of `def_id`'s parent in the def tree. If /// this returns `None`, then `def_id` represents a crate root or /// inlined root. - fn parent_def_id(&self, def_id: DefId) -> Option { + pub fn parent_def_id(self, def_id: DefId) -> Option { let key = self.def_key(def_id); key.parent.map(|index| DefId { krate: def_id.krate, index: index }) } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 8aba6329b090b..8171a99beb90f 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -193,7 +193,7 @@ impl<'tcx> ImplOrTraitItem<'tcx> { match *self { ConstTraitItem(ref associated_const) => Def::AssociatedConst(associated_const.def_id), MethodTraitItem(ref method) => Def::Method(method.def_id), - TypeTraitItem(ref ty) => Def::AssociatedTy(ty.container.id(), ty.def_id), + TypeTraitItem(ref ty) => Def::AssociatedTy(ty.def_id), } } @@ -1666,7 +1666,7 @@ impl<'a, 'gcx, 'tcx, 'container> AdtDefData<'gcx, 'container> { pub fn variant_of_def(&self, def: Def) -> &VariantDefData<'gcx, 'container> { match def { - Def::Variant(_, vid) => self.variant_with_id(vid), + Def::Variant(vid) => self.variant_with_id(vid), Def::Struct(..) | Def::Union(..) | Def::TyAlias(..) | Def::AssociatedTy(..) => self.struct_variant(), _ => bug!("unexpected def {:?} in variant_of_def", def) @@ -2325,7 +2325,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // or variant or their constructors, panics otherwise. pub fn expect_variant_def(self, def: Def) -> VariantDef<'tcx> { match def { - Def::Variant(enum_did, did) => { + Def::Variant(did) => { + let enum_did = self.parent_def_id(did).unwrap(); self.lookup_adt_def(enum_did).variant_with_id(did) } Def::Struct(did) | Def::Union(did) => { @@ -2387,7 +2388,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { if let Some(id) = self.map.as_local_node_id(id) { self.map.name(id) } else { - self.sess.cstore.item_name(id) + self.sess.cstore.opt_item_name(id).unwrap_or_else(|| { + bug!("item_name: no name for {:?}", self.def_path(id)); + }) } } @@ -2631,11 +2634,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let trait_ref = self.impl_trait_ref(impl_def_id).unwrap(); // Record the trait->implementation mapping. - if let Some(parent) = self.sess.cstore.impl_parent(impl_def_id) { - def.record_remote_impl(self, impl_def_id, trait_ref, parent); - } else { - def.record_remote_impl(self, impl_def_id, trait_ref, trait_id); - } + let parent = self.sess.cstore.impl_parent(impl_def_id).unwrap_or(trait_id); + def.record_remote_impl(self, impl_def_id, trait_ref, parent); // For any methods that use a default implementation, add them to // the map. This is a bit unfortunate. diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs index 8af06286189b1..eb74936d8c905 100644 --- a/src/librustc_const_eval/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -801,7 +801,7 @@ fn pat_constructors(cx: &MatchCheckCtxt, p: &Pat, match pat.node { PatKind::Struct(..) | PatKind::TupleStruct(..) | PatKind::Path(..) => match cx.tcx.expect_def(pat.id) { - Def::Variant(_, id) => vec![Variant(id)], + Def::Variant(id) => vec![Variant(id)], Def::Struct(..) | Def::Union(..) | Def::TyAlias(..) | Def::AssociatedTy(..) => vec![Single], Def::Const(..) | Def::AssociatedConst(..) => @@ -913,7 +913,7 @@ pub fn specialize<'a, 'b, 'tcx>( Def::Const(..) | Def::AssociatedConst(..) => span_bug!(pat_span, "const pattern should've \ been rewritten"), - Def::Variant(_, id) if *constructor != Variant(id) => None, + Def::Variant(id) if *constructor != Variant(id) => None, Def::Variant(..) | Def::Struct(..) => Some(Vec::new()), def => span_bug!(pat_span, "specialize: unexpected \ definition {:?}", def), @@ -925,7 +925,7 @@ pub fn specialize<'a, 'b, 'tcx>( Def::Const(..) | Def::AssociatedConst(..) => span_bug!(pat_span, "const pattern should've \ been rewritten"), - Def::Variant(_, id) if *constructor != Variant(id) => None, + Def::Variant(id) if *constructor != Variant(id) => None, Def::Variant(..) | Def::Struct(..) => { match ddpos { Some(ddpos) => { diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index aa53fdd6e7e27..dce3882004c67 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -57,7 +57,6 @@ macro_rules! math { } fn lookup_variant_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - enum_def: DefId, variant_def: DefId) -> Option<&'tcx Expr> { fn variant_expr<'a>(variants: &'a [hir::Variant], id: ast::NodeId) @@ -70,8 +69,8 @@ fn lookup_variant_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, None } - if let Some(enum_node_id) = tcx.map.as_local_node_id(enum_def) { - let variant_node_id = tcx.map.as_local_node_id(variant_def).unwrap(); + if let Some(variant_node_id) = tcx.map.as_local_node_id(variant_def) { + let enum_node_id = tcx.map.get_parent(variant_node_id); match tcx.map.find(enum_node_id) { None => None, Some(ast_map::NodeItem(it)) => match it.node { @@ -289,7 +288,7 @@ pub fn const_expr_to_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } let path = match def { Def::Struct(def_id) => def_to_path(tcx, def_id), - Def::Variant(_, variant_did) => def_to_path(tcx, variant_did), + Def::Variant(variant_did) => def_to_path(tcx, variant_did), Def::Fn(..) | Def::Method(..) => return Ok(P(hir::Pat { id: expr.id, node: PatKind::Lit(P(expr.clone())), @@ -808,8 +807,8 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, signal!(e, NonConstPath); } }, - Def::Variant(enum_def, variant_def) => { - if let Some(const_expr) = lookup_variant_by_id(tcx, enum_def, variant_def) { + Def::Variant(variant_def) => { + if let Some(const_expr) = lookup_variant_by_id(tcx, variant_def) { match eval_const_expr_partial(tcx, const_expr, ty_hint, None) { Ok(val) => val, Err(err) => { diff --git a/src/librustc_incremental/calculate_svh/svh_visitor.rs b/src/librustc_incremental/calculate_svh/svh_visitor.rs index af8ec6c62578f..9950f470a82c4 100644 --- a/src/librustc_incremental/calculate_svh/svh_visitor.rs +++ b/src/librustc_incremental/calculate_svh/svh_visitor.rs @@ -602,7 +602,6 @@ impl<'a, 'hash, 'tcx> StrictVersionHashVisitor<'a, 'hash, 'tcx> { // def-id is the same, so it suffices to hash the def-id Def::Fn(..) | Def::Mod(..) | - Def::ForeignMod(..) | Def::Static(..) | Def::Variant(..) | Def::Enum(..) | diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs index c687353d437c1..518e662441218 100644 --- a/src/librustc_metadata/astencode.rs +++ b/src/librustc_metadata/astencode.rs @@ -18,7 +18,7 @@ use cstore::CrateMetadata; use decoder::DecodeContext; use encoder::EncodeContext; -use middle::cstore::{InlinedItem, InlinedItemRef}; +use rustc::middle::cstore::{InlinedItem, InlinedItemRef}; use rustc::hir::def; use rustc::hir::def_id::DefId; use rustc::ty::TyCtxt; diff --git a/src/librustc_metadata/common.rs b/src/librustc_metadata/common.rs index 04b9b7f7c6713..e068395f729a4 100644 --- a/src/librustc_metadata/common.rs +++ b/src/librustc_metadata/common.rs @@ -10,29 +10,36 @@ #![allow(non_camel_case_types, non_upper_case_globals)] +use rustc::hir; +use rustc::hir::def; +use rustc::hir::def_id::{DefIndex, DefId}; use rustc::ty; +use rustc::session::config::PanicStrategy; #[derive(Clone, Copy, Debug, PartialEq, RustcEncodable, RustcDecodable)] pub enum Family { ImmStatic, MutStatic, + ForeignImmStatic, + ForeignMutStatic, Fn, + ForeignFn, Method, AssociatedType, Type, Mod, ForeignMod, Enum, - Variant(ty::VariantKind), + Variant, Impl, DefaultImpl, Trait, - Struct(ty::VariantKind), + Struct, Union, - PublicField, - InheritedField, + Field, Const, AssociatedConst, + Closure } // NB: increment this if you change the format of metadata such that @@ -48,68 +55,151 @@ pub fn rustc_version() -> String { ) } +#[derive(RustcEncodable, RustcDecodable)] +pub struct CrateInfo { + pub name: String, + pub triple: String, + pub hash: hir::svh::Svh, + pub disambiguator: String, + pub panic_strategy: PanicStrategy, + pub plugin_registrar_fn: Option, + pub macro_derive_registrar: Option +} + pub mod root_tag { pub const rustc_version: usize = 0x10f; - pub const crate_deps: usize = 0x102; - pub const crate_hash: usize = 0x103; - pub const crate_crate_name: usize = 0x104; - pub const crate_disambiguator: usize = 0x113; - pub const items: usize = 0x100; + + pub const crate_info: usize = 0x104; + pub const index: usize = 0x110; pub const xref_index: usize = 0x111; pub const xref_data: usize = 0x112; - pub const crate_triple: usize = 0x105; + pub const crate_deps: usize = 0x102; pub const dylib_dependency_formats: usize = 0x106; + pub const native_libraries: usize = 0x10a; pub const lang_items: usize = 0x107; pub const lang_items_missing: usize = 0x76; pub const impls: usize = 0x109; - pub const native_libraries: usize = 0x10a; - pub const plugin_registrar_fn: usize = 0x10b; - pub const panic_strategy: usize = 0x114; - pub const macro_derive_registrar: usize = 0x115; pub const reachable_ids: usize = 0x10c; pub const macro_defs: usize = 0x10e; pub const codemap: usize = 0xa1; } +#[derive(RustcEncodable, RustcDecodable)] +pub struct ModData { + pub reexports: Vec +} + +#[derive(RustcEncodable, RustcDecodable)] +pub struct VariantData { + pub kind: ty::VariantKind, + pub disr: u64, + + /// If this is a struct's only variant, this + /// is the index of the "struct ctor" item. + pub struct_ctor: Option +} + +#[derive(RustcEncodable, RustcDecodable)] +pub struct TraitData { + pub unsafety: hir::Unsafety, + pub paren_sugar: bool, + pub has_default_impl: bool +} + +#[derive(RustcEncodable, RustcDecodable)] +pub struct ImplData { + pub polarity: hir::ImplPolarity, + pub parent_impl: Option, + pub coerce_unsized_kind: Option, +} + +#[derive(RustcEncodable, RustcDecodable)] +pub struct TraitAssociatedData { + pub has_default: bool +} + +#[derive(RustcEncodable, RustcDecodable)] +pub struct ImplAssociatedData { + pub defaultness: hir::Defaultness, + pub constness: hir::Constness +} + +#[derive(RustcEncodable, RustcDecodable)] +pub struct FnData { + pub constness: hir::Constness +} + +#[derive(RustcEncodable, RustcDecodable)] +pub struct ClosureData { + pub kind: ty::ClosureKind +} + +#[derive(RustcEncodable, RustcDecodable)] +pub enum EntryData { + Other, + Mod(ModData), + Variant(VariantData), + Trait(TraitData), + Impl(ImplData), + TraitAssociated(TraitAssociatedData), + ImplAssociated(ImplAssociatedData), + Fn(FnData), + Closure(ClosureData) +} + +#[derive(RustcEncodable, RustcDecodable)] +pub struct TraitTypedData<'tcx> { + pub trait_ref: ty::TraitRef<'tcx> +} + +#[derive(RustcEncodable, RustcDecodable)] +pub struct ImplTypedData<'tcx> { + pub trait_ref: Option> +} + +#[derive(RustcEncodable, RustcDecodable)] +pub struct MethodTypedData<'tcx> { + pub explicit_self: ty::ExplicitSelfCategory<'tcx> +} + +#[derive(RustcEncodable, RustcDecodable)] +pub struct ClosureTypedData<'tcx> { + pub ty: ty::ClosureTy<'tcx> +} + +#[derive(RustcEncodable, RustcDecodable)] +pub enum EntryTypedData<'tcx> { + Other, + Trait(TraitTypedData<'tcx>), + Impl(ImplTypedData<'tcx>), + Method(MethodTypedData<'tcx>), + Closure(ClosureTypedData<'tcx>) +} + pub mod item_tag { - pub const name: usize = 0x20; - pub const def_index: usize = 0x21; - pub const family: usize = 0x24; - pub const ty: usize = 0x25; - pub const parent_item: usize = 0x28; - pub const is_tuple_struct_ctor: usize = 0x29; - pub const closure_kind: usize = 0x2a; - pub const closure_ty: usize = 0x2b; pub const def_key: usize = 0x2c; + pub const family: usize = 0x24; pub const attributes: usize = 0x101; - pub const trait_ref: usize = 0x3b; - pub const disr_val: usize = 0x3c; - pub const fields: usize = 0x41; - pub const variances: usize = 0x43; - pub const trait_method_explicit_self: usize = 0x45; - pub const ast: usize = 0x50; - pub const mir: usize = 0x52; - pub const trait_item_has_body: usize = 0x70; pub const visibility: usize = 0x78; - pub const inherent_impls: usize = 0x79; pub const children: usize = 0x7b; - pub const method_argument_names: usize = 0x85; pub const stability: usize = 0x88; - pub const repr: usize = 0x89; - pub const struct_ctor: usize = 0x8b; + pub const deprecation: usize = 0xa7; + + pub const ty: usize = 0x25; + pub const inherent_impls: usize = 0x79; + pub const variances: usize = 0x43; pub const generics: usize = 0x8f; pub const predicates: usize = 0x95; - pub const unsafety: usize = 0x9a; - pub const polarity: usize = 0x9d; - pub const paren_sugar: usize = 0xa0; pub const super_predicates: usize = 0xa3; - pub const defaulted_trait: usize = 0xa4; - pub const impl_coerce_unsized_kind: usize = 0xa5; - pub const constness: usize = 0xa6; - pub const deprecation: usize = 0xa7; - pub const defaultness: usize = 0xa8; - pub const parent_impl: usize = 0xa9; + + pub const ast: usize = 0x50; + pub const mir: usize = 0x52; + + pub const data: usize = 0x3c; + pub const typed_data: usize = 0x3d; + + pub const fn_arg_names: usize = 0x85; } /// The shorthand encoding of `Ty` uses `TypeVariants`' variant `usize` diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 7b6ed4e6b7648..dd6ef73ccdbd7 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -12,6 +12,7 @@ //! Validates all used crates and extern libraries and loads their metadata +use common::CrateInfo; use cstore::{self, CStore, CrateSource, MetadataBlob}; use decoder; use loader::{self, CratePaths}; @@ -85,7 +86,7 @@ fn should_link(i: &ast::Item) -> bool { } #[derive(Debug)] -struct CrateInfo { +struct ExternCrateInfo { ident: String, name: String, id: ast::NodeId, @@ -183,7 +184,7 @@ impl<'a> CrateReader<'a> { } } - fn extract_crate_info(&self, i: &ast::Item) -> Option { + fn extract_crate_info(&self, i: &ast::Item) -> Option { match i.node { ast::ItemKind::ExternCrate(ref path_opt) => { debug!("resolving extern crate stmt. ident: {} path_opt: {:?}", @@ -196,7 +197,7 @@ impl<'a> CrateReader<'a> { } None => i.ident.to_string(), }; - Some(CrateInfo { + Some(ExternCrateInfo { ident: i.ident.to_string(), name: name, id: i.id, @@ -258,32 +259,28 @@ impl<'a> CrateReader<'a> { fn verify_no_symbol_conflicts(&self, span: Span, - metadata: &MetadataBlob) { - let disambiguator = decoder::get_crate_disambiguator(metadata.as_slice()); - let crate_name = decoder::get_crate_name(metadata.as_slice()); - + info: &CrateInfo) { // Check for (potential) conflicts with the local crate - if self.local_crate_name == crate_name && - self.sess.local_crate_disambiguator() == &disambiguator[..] { + if self.local_crate_name == info.name && + self.sess.local_crate_disambiguator() == &info.disambiguator[..] { span_fatal!(self.sess, span, E0519, "the current crate is indistinguishable from one of its \ dependencies: it has the same crate-name `{}` and was \ compiled with the same `-C metadata` arguments. This \ will result in symbol conflicts between the two.", - crate_name) + info.name) } - let svh = decoder::get_crate_hash(metadata.as_slice()); // Check for conflicts with any crate loaded so far self.cstore.iter_crate_data(|_, other| { - if other.name() == crate_name && // same crate-name - other.disambiguator() == disambiguator && // same crate-disambiguator - other.hash() != svh { // but different SVH + if other.name() == info.name && // same crate-name + other.disambiguator() == info.disambiguator && // same crate-disambiguator + other.hash() != info.hash { // but different SVH span_fatal!(self.sess, span, E0523, "found two different crates with name `{}` that are \ not distinguished by differing `-C metadata`. This \ will result in symbol conflicts between the two.", - crate_name) + info.name) } }); } @@ -298,7 +295,8 @@ impl<'a> CrateReader<'a> { -> (CrateNum, Rc, cstore::CrateSource) { info!("register crate `extern crate {} as {}`", name, ident); - self.verify_no_symbol_conflicts(span, &lib.metadata); + let crate_info = decoder::get_crate_info(lib.metadata.as_slice()); + self.verify_no_symbol_conflicts(span, &crate_info); // Claim this crate number and cache it let cnum = self.next_crate_num; @@ -321,9 +319,15 @@ impl<'a> CrateReader<'a> { let cnum_map = self.resolve_crate_deps(root, metadata.as_slice(), cnum, span); + if crate_info.macro_derive_registrar.is_some() { + self.sess.span_err(span, "crates of the `rustc-macro` crate type \ + cannot be linked at runtime"); + } + let cmeta = Rc::new(cstore::CrateMetadata { name: name.to_string(), extern_crate: Cell::new(None), + info: crate_info, index: decoder::load_index(metadata.as_slice()), xref_index: decoder::load_xrefs(metadata.as_slice()), key_map: decoder::load_key_map(metadata.as_slice()), @@ -334,11 +338,6 @@ impl<'a> CrateReader<'a> { explicitly_linked: Cell::new(explicitly_linked), }); - if decoder::get_derive_registrar_fn(cmeta.data.as_slice()).is_some() { - self.sess.span_err(span, "crates of the `rustc-macro` crate type \ - cannot be linked at runtime"); - } - let source = cstore::CrateSource { dylib: dylib, rlib: rlib, @@ -416,13 +415,11 @@ impl<'a> CrateReader<'a> { // Note that we only do this for target triple crates, though, as we // don't want to match a host crate against an equivalent target one // already loaded. + let crate_info = decoder::get_crate_info(library.metadata.as_slice()); if loader.triple == self.sess.opts.target_triple { - let meta_hash = decoder::get_crate_hash(library.metadata.as_slice()); - let meta_name = decoder::get_crate_name(library.metadata.as_slice()) - .to_string(); let mut result = LoadResult::Loaded(library); self.cstore.iter_crate_data(|cnum, data| { - if data.name() == meta_name && meta_hash == data.hash() { + if data.name() == crate_info.name && crate_info.hash == data.hash() { assert!(loader.hash.is_none()); info!("load success, going to previous cnum: {}", cnum); result = LoadResult::Previous(cnum); @@ -497,7 +494,7 @@ impl<'a> CrateReader<'a> { }).collect() } - fn read_extension_crate(&mut self, span: Span, info: &CrateInfo) -> ExtensionCrate { + fn read_extension_crate(&mut self, span: Span, info: &ExternCrateInfo) -> ExtensionCrate { info!("read extension crate {} `extern crate {} as {}` linked={}", info.id, info.name, info.ident, info.should_link); let target_triple = &self.sess.opts.target_triple[..]; @@ -570,11 +567,12 @@ impl<'a> CrateReader<'a> { let ci = self.extract_crate_info(item).unwrap(); let ekrate = self.read_extension_crate(item.span, &ci); + let crate_info = decoder::get_crate_info(ekrate.metadata.as_slice()); let source_name = format!("<{} macros>", item.ident); let mut ret = Macros { macro_rules: Vec::new(), custom_derive_registrar: None, - svh: decoder::get_crate_hash(ekrate.metadata.as_slice()), + svh: crate_info.hash, dylib: None, }; decoder::each_exported_macro(ekrate.metadata.as_slice(), @@ -619,7 +617,7 @@ impl<'a> CrateReader<'a> { true }); - match decoder::get_derive_registrar_fn(ekrate.metadata.as_slice()) { + match crate_info.macro_derive_registrar { Some(id) => ret.custom_derive_registrar = Some(id), // If this crate is not a rustc-macro crate then we might be able to @@ -656,7 +654,7 @@ impl<'a> CrateReader<'a> { /// SVH and DefIndex of the registrar function. pub fn find_plugin_registrar(&mut self, span: Span, name: &str) -> Option<(PathBuf, Svh, DefIndex)> { - let ekrate = self.read_extension_crate(span, &CrateInfo { + let ekrate = self.read_extension_crate(span, &ExternCrateInfo { name: name.to_string(), ident: name.to_string(), id: ast::DUMMY_NODE_ID, @@ -673,13 +671,10 @@ impl<'a> CrateReader<'a> { span_fatal!(self.sess, span, E0456, "{}", &message[..]); } - let svh = decoder::get_crate_hash(ekrate.metadata.as_slice()); - let registrar = - decoder::get_plugin_registrar_fn(ekrate.metadata.as_slice()); - - match (ekrate.dylib.as_ref(), registrar) { + let crate_info = decoder::get_crate_info(ekrate.metadata.as_slice()); + match (ekrate.dylib.as_ref(), crate_info.plugin_registrar_fn) { (Some(dylib), Some(reg)) => { - Some((dylib.to_path_buf(), svh, reg)) + Some((dylib.to_path_buf(), crate_info.hash, reg)) } (None, Some(_)) => { span_err!(self.sess, span, E0457, diff --git a/src/librustc_metadata/csearch.rs b/src/librustc_metadata/csearch.rs index c4ce7af269daa..f650155c03546 100644 --- a/src/librustc_metadata/csearch.rs +++ b/src/librustc_metadata/csearch.rs @@ -14,10 +14,10 @@ use decoder; use encoder; use loader; -use middle::cstore::{InlinedItem, CrateStore, CrateSource, ChildItem, ExternCrate}; -use middle::cstore::{NativeLibraryKind, LinkMeta, LinkagePreference}; +use rustc::middle::cstore::{InlinedItem, CrateStore, CrateSource, ChildItem, ExternCrate}; +use rustc::middle::cstore::{NativeLibraryKind, LinkMeta, LinkagePreference}; use rustc::hir::def; -use middle::lang_items; +use rustc::middle::lang_items; use rustc::ty::{self, Ty, TyCtxt}; use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX}; @@ -77,12 +77,6 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { decoder::get_item_variances(&cdata, def.index) } - fn repr_attrs(&self, def: DefId) -> Vec { - self.dep_graph.read(DepNode::MetaData(def)); - let cdata = self.get_crate_data(def.krate); - decoder::get_repr_attrs(&cdata, def.index) - } - fn item_type<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> Ty<'tcx> { @@ -136,23 +130,21 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { decoder::get_adt_def(&cdata, def.index, tcx) } - fn method_arg_names(&self, did: DefId) -> Vec + fn fn_arg_names(&self, did: DefId) -> Vec { self.dep_graph.read(DepNode::MetaData(did)); let cdata = self.get_crate_data(did.krate); - decoder::get_method_arg_names(&cdata, did.index) - } - - fn item_name(&self, def: DefId) -> ast::Name { - self.dep_graph.read(DepNode::MetaData(def)); - let cdata = self.get_crate_data(def.krate); - decoder::get_item_name(&cdata, def.index) + decoder::get_fn_arg_names(&cdata, did.index) } fn opt_item_name(&self, def: DefId) -> Option { self.dep_graph.read(DepNode::MetaData(def)); let cdata = self.get_crate_data(def.krate); - decoder::maybe_get_item_name(&cdata, def.index) + if def.index == CRATE_DEF_INDEX { + Some(token::intern(&cdata.name())) + } else { + decoder::maybe_get_item_name(&cdata, def.index) + } } fn inherent_implementations_for_type(&self, def_id: DefId) -> Vec @@ -183,10 +175,9 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { self.dep_graph.read(DepNode::MetaData(def_id)); let mut result = vec![]; let crate_data = self.get_crate_data(def_id.krate); - let get_crate_data = |cnum| self.get_crate_data(cnum); - decoder::each_child_of_item(&crate_data, def_id.index, get_crate_data, |def, _, _| { - result.push(def.def_id()); - }); + let get_crate_data = &mut |cnum| self.get_crate_data(cnum); + decoder::each_child_of_item(&crate_data, def_id.index, get_crate_data, + &mut |def, _, _| result.push(def.def_id())); result } @@ -339,20 +330,17 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { fn crate_hash(&self, cnum: CrateNum) -> Svh { - let cdata = self.get_crate_data(cnum); - decoder::get_crate_hash(cdata.data()) + self.get_crate_hash(cnum) } fn crate_disambiguator(&self, cnum: CrateNum) -> token::InternedString { - let cdata = self.get_crate_data(cnum); - token::intern_and_get_ident(&decoder::get_crate_disambiguator(cdata.data())) + token::intern_and_get_ident(&self.get_crate_data(cnum).disambiguator()) } fn plugin_registrar_fn(&self, cnum: CrateNum) -> Option { - let cdata = self.get_crate_data(cnum); - decoder::get_plugin_registrar_fn(cdata.data()).map(|index| DefId { + self.get_crate_data(cnum).info.plugin_registrar_fn.map(|index| DefId { krate: cnum, index: index }) @@ -412,13 +400,6 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { decoder::get_struct_ctor_def_id(&cdata, struct_def_id.index) } - fn tuple_struct_definition_if_ctor(&self, did: DefId) -> Option - { - self.dep_graph.read(DepNode::MetaData(did)); - let cdata = self.get_crate_data(did.krate); - decoder::get_tuple_struct_definition_if_ctor(&cdata, did.index) - } - fn struct_field_names(&self, def: DefId) -> Vec { self.dep_graph.read(DepNode::MetaData(def)); @@ -431,8 +412,9 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { self.dep_graph.read(DepNode::MetaData(def_id)); let mut result = vec![]; let crate_data = self.get_crate_data(def_id.krate); - let get_crate_data = |cnum| self.get_crate_data(cnum); - decoder::each_child_of_item(&crate_data, def_id.index, get_crate_data, |def, name, vis| { + let get_crate_data = &mut |cnum| self.get_crate_data(cnum); + decoder::each_child_of_item(&crate_data, def_id.index, get_crate_data, + &mut |def, name, vis| { result.push(ChildItem { def: def, name: name, vis: vis }); }); result @@ -497,45 +479,17 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { }; match inlined { - decoder::FoundAst::NotFound => { + None => { self.inlined_item_cache .borrow_mut() .insert(def_id, None); } - decoder::FoundAst::Found(&InlinedItem::Item(d, ref item)) => { + Some(&InlinedItem::Item(d, ref item)) => { assert_eq!(d, def_id); let inlined_root_node_id = find_inlined_item_root(item.id); cache_inlined_item(def_id, item.id, inlined_root_node_id); } - decoder::FoundAst::FoundParent(parent_did, item) => { - let inlined_root_node_id = find_inlined_item_root(item.id); - cache_inlined_item(parent_did, item.id, inlined_root_node_id); - - match item.node { - hir::ItemEnum(ref ast_def, _) => { - let ast_vs = &ast_def.variants; - let ty_vs = &tcx.lookup_adt_def(parent_did).variants; - assert_eq!(ast_vs.len(), ty_vs.len()); - for (ast_v, ty_v) in ast_vs.iter().zip(ty_vs.iter()) { - cache_inlined_item(ty_v.did, - ast_v.node.data.id(), - inlined_root_node_id); - } - } - hir::ItemStruct(ref struct_def, _) => { - if struct_def.is_struct() { - bug!("instantiate_inline: called on a non-tuple struct") - } else { - cache_inlined_item(def_id, - struct_def.id(), - inlined_root_node_id); - } - } - _ => bug!("instantiate_inline: item has a \ - non-enum, non-struct parent") - } - } - decoder::FoundAst::Found(&InlinedItem::TraitItem(_, ref trait_item)) => { + Some(&InlinedItem::TraitItem(_, ref trait_item)) => { let inlined_root_node_id = find_inlined_item_root(trait_item.id); cache_inlined_item(def_id, trait_item.id, inlined_root_node_id); @@ -548,7 +502,7 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { tcx.impl_or_trait_items.borrow_mut() .insert(trait_item_def_id, ty_trait_item); } - decoder::FoundAst::Found(&InlinedItem::ImplItem(_, ref impl_item)) => { + Some(&InlinedItem::ImplItem(_, ref impl_item)) => { let inlined_root_node_id = find_inlined_item_root(impl_item.id); cache_inlined_item(def_id, impl_item.id, inlined_root_node_id); } diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index 7aa4677353bb2..c6cbe6db9098b 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -39,9 +39,9 @@ use syntax::attr; use syntax::codemap; use syntax_pos; -pub use middle::cstore::{NativeLibraryKind, LinkagePreference}; -pub use middle::cstore::{NativeStatic, NativeFramework, NativeUnknown}; -pub use middle::cstore::{CrateSource, LinkMeta}; +pub use rustc::middle::cstore::{NativeLibraryKind, LinkagePreference}; +pub use rustc::middle::cstore::{NativeStatic, NativeFramework, NativeUnknown}; +pub use rustc::middle::cstore::{CrateSource, LinkMeta}; // A map from external crate numbers (as decoded from some crate file) to // local crate numbers (as generated during this session). Each external @@ -78,6 +78,7 @@ pub struct CrateMetadata { pub cnum: CrateNum, pub codemap_import_info: RefCell>, + pub info: common::CrateInfo, pub index: index::Index, pub xref_index: index::DenseIndex, @@ -143,8 +144,7 @@ impl CStore { } pub fn get_crate_hash(&self, cnum: CrateNum) -> Svh { - let cdata = self.get_crate_data(cnum); - decoder::get_crate_hash(cdata.data()) + self.get_crate_data(cnum).hash() } pub fn set_crate_data(&self, cnum: CrateNum, data: Rc) { @@ -299,11 +299,9 @@ impl CStore { impl CrateMetadata { pub fn data<'a>(&'a self) -> &'a [u8] { self.data.as_slice() } - pub fn name(&self) -> String { decoder::get_crate_name(self.data()) } - pub fn hash(&self) -> Svh { decoder::get_crate_hash(self.data()) } - pub fn disambiguator(&self) -> String { - decoder::get_crate_disambiguator(self.data()) - } + pub fn name(&self) -> &str { &self.info.name } + pub fn hash(&self) -> Svh { self.info.hash } + pub fn disambiguator(&self) -> &str { &self.info.disambiguator } pub fn imported_filemaps<'a>(&'a self, codemap: &codemap::CodeMap) -> Ref<'a, Vec> { let filemaps = self.codemap_import_info.borrow(); @@ -352,7 +350,7 @@ impl CrateMetadata { } pub fn panic_strategy(&self) -> PanicStrategy { - decoder::get_panic_strategy(self.data()) + self.info.panic_strategy.clone() } } diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 662236be0f0d2..f3283451b93b8 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -15,25 +15,22 @@ use astencode::decode_inlined_item; use cstore::{self, CrateMetadata}; use common::*; -use common::Family::*; -use def_key; use index; use rustc::hir::def_id::CRATE_DEF_INDEX; use rustc::hir::svh::Svh; use rustc::hir::map as hir_map; -use rustc::hir::map::DefKey; +use rustc::hir::map::{DefKey, DefPathData}; use rustc::util::nodemap::FnvHashMap; use rustc::hir; use rustc::hir::intravisit::IdRange; -use rustc::session::config::PanicStrategy; -use middle::cstore::{InlinedItem, LinkagePreference}; -use rustc::hir::def::{self, Def}; +use rustc::middle::cstore::{InlinedItem, LinkagePreference}; +use rustc::hir::def::Def; use rustc::hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE}; -use middle::lang_items; +use rustc::middle::lang_items; use rustc::ty::{ImplContainer, TraitContainer}; -use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; +use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::subst::Substs; use rustc_const_math::ConstInt; @@ -51,6 +48,7 @@ use rbml; use rustc_serialize::{Decodable, Decoder, SpecializedDecoder, opaque}; use syntax::attr; use syntax::ast::{self, NodeId}; +use syntax::parse::token; use syntax_pos::{self, Span, BytePos}; pub struct DecodeContext<'a, 'tcx: 'a> { @@ -101,12 +99,6 @@ impl<'a, 'tcx> DecodeContext<'a, 'tcx> { self.decode() }) } - - pub fn seq_mut<'b, T: Decodable>(&'b mut self) -> impl Iterator + 'b { - (0..self.read_usize().unwrap()).map(move |_| { - self.decode() - }) - } } macro_rules! decoder_methods { @@ -321,6 +313,13 @@ impl CrateMetadata { Some(d) => d } } + + fn local_def_id(&self, index: DefIndex) -> DefId { + DefId { + krate: self.cnum, + index: index + } + } } pub fn load_index(data: &[u8]) -> index::Index { @@ -342,12 +341,10 @@ pub fn load_xrefs(data: &[u8]) -> index::DenseIndex { // Go through each item in the metadata and create a map from that // item's def-key to the item's DefIndex. pub fn load_key_map(data: &[u8]) -> FnvHashMap { - rbml::Doc::new(data).get(root_tag::items).children().map(|item_doc| { + load_index(data).iter_enumerated(data).map(|(index, pos)| { // load def-key from item - let key = item_def_key(item_doc); - - // load def-index from item - (key, item_doc.get(item_tag::def_index).decoder().decode()) + let key = item_def_key(rbml::Doc::at(data, pos as usize)); + (key, index) }).collect() } @@ -356,38 +353,27 @@ fn item_family(item: rbml::Doc) -> Family { } fn item_visibility(item: rbml::Doc) -> ty::Visibility { - match reader::maybe_get_doc(item, item_tag::visibility) { - None => ty::Visibility::Public, - Some(visibility_doc) => visibility_doc.decoder().decode() - } + item.get(item_tag::visibility).decoder().decode() } -fn item_defaultness(item: rbml::Doc) -> hir::Defaultness { - match reader::maybe_get_doc(item, item_tag::defaultness) { - None => hir::Defaultness::Default, // should occur only for default impls on traits - Some(defaultness_doc) => defaultness_doc.decoder().decode() - } -} +fn entry_data(doc: rbml::Doc, cdata: Cmd) -> EntryData { + let mut dcx = doc.get(item_tag::data).decoder(); + dcx.cdata = Some(cdata); -fn item_parent_item(cdata: Cmd, d: rbml::Doc) -> Option { - reader::maybe_get_doc(d, item_tag::parent_item).map(|did| { - let mut dcx = did.decoder(); - dcx.cdata = Some(cdata); - dcx.decode() - }) + dcx.decode() } -fn item_require_parent_item(cdata: Cmd, d: rbml::Doc) -> DefId { - let mut dcx = d.get(item_tag::parent_item).decoder(); +fn entry_typed_data<'a, 'tcx>(doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>, cdata: Cmd) + -> EntryTypedData<'tcx> { + let mut dcx = doc.get(item_tag::typed_data).decoder(); dcx.cdata = Some(cdata); + dcx.tcx = Some(tcx); + dcx.decode() } -fn item_def_id(d: rbml::Doc, cdata: Cmd) -> DefId { - DefId { - krate: cdata.cnum, - index: d.get(item_tag::def_index).decoder().decode() - } +fn item_parent_item(cdata: Cmd, d: rbml::Doc) -> Option { + item_def_key(d).parent.map(|index| cdata.local_def_id(index)) } fn doc_type<'a, 'tcx>(doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>, cdata: Cmd) -> Ty<'tcx> { @@ -404,53 +390,63 @@ fn maybe_doc_type<'a, 'tcx>(doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>, cdata: }) } -fn doc_trait_ref<'a, 'tcx>(doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>, cdata: Cmd) - -> ty::TraitRef<'tcx> { - let mut dcx = doc.decoder(); - dcx.tcx = Some(tcx); - dcx.cdata = Some(cdata); - dcx.decode() -} - fn item_name(item: rbml::Doc) -> ast::Name { maybe_item_name(item).expect("no item in item_name") } fn maybe_item_name(item: rbml::Doc) -> Option { - reader::maybe_get_doc(item, item_tag::name).map(|name| { - name.decoder().decode() - }) -} + let name = match item_def_key(item).disambiguated_data.data { + DefPathData::TypeNs(name) | + DefPathData::ValueNs(name) | + DefPathData::Module(name) | + DefPathData::MacroDef(name) | + DefPathData::TypeParam(name) | + DefPathData::LifetimeDef(name) | + DefPathData::EnumVariant(name) | + DefPathData::Field(name) | + DefPathData::Binding(name) => Some(name), + + DefPathData::InlinedRoot(_) => bug!("unexpected DefPathData"), + + DefPathData::CrateRoot | + DefPathData::Misc | + DefPathData::Impl | + DefPathData::ClosureExpr | + DefPathData::StructCtor | + DefPathData::Initializer | + DefPathData::ImplTrait => None + }; -fn item_to_def(cdata: Cmd, item: rbml::Doc, did: DefId) -> Option { - Some(match item_family(item) { - Family::Const => Def::Const(did), - Family::AssociatedConst => Def::AssociatedConst(did), - Family::ImmStatic => Def::Static(did, false), - Family::MutStatic => Def::Static(did, true), - Family::Struct(..) => Def::Struct(did), - Family::Union => Def::Union(did), - Family::Fn => Def::Fn(did), - Family::Method => Def::Method(did), - Family::Type => Def::TyAlias(did), - Family::AssociatedType => { - Def::AssociatedTy(item_require_parent_item(cdata, item), did) - } - Family::Mod => Def::Mod(did), - Family::ForeignMod => Def::ForeignMod(did), - Family::Variant(..) => { - Def::Variant(item_require_parent_item(cdata, item), did) - } - Family::Trait => Def::Trait(did), - Family::Enum => Def::Enum(did), - - Family::Impl | - Family::DefaultImpl | - Family::PublicField | - Family::InheritedField => { - return None - } - }) + name.map(|s| token::intern(&s)) +} + +impl Family { + fn to_def(&self, did: DefId) -> Option { + Some(match *self { + Family::Const => Def::Const(did), + Family::AssociatedConst => Def::AssociatedConst(did), + Family::ImmStatic | Family::ForeignImmStatic => Def::Static(did, false), + Family::MutStatic | Family::ForeignMutStatic => Def::Static(did, true), + Family::Struct => Def::Struct(did), + Family::Union => Def::Union(did), + Family::Fn | Family::ForeignFn => Def::Fn(did), + Family::Method => Def::Method(did), + Family::Type => Def::TyAlias(did), + Family::AssociatedType => Def::AssociatedTy(did), + Family::Mod => Def::Mod(did), + Family::Variant => Def::Variant(did), + Family::Trait => Def::Trait(did), + Family::Enum => Def::Enum(did), + + Family::ForeignMod | + Family::Impl | + Family::DefaultImpl | + Family::Field | + Family::Closure => { + return None + } + }) + } } pub fn get_trait_def<'a, 'tcx>(cdata: Cmd, @@ -459,13 +455,46 @@ pub fn get_trait_def<'a, 'tcx>(cdata: Cmd, { let item_doc = cdata.lookup_item(item_id); let generics = doc_generics(item_doc, tcx, cdata); - let unsafety = item_doc.get(item_tag::unsafety).decoder().decode(); - let paren_sugar = item_doc.get(item_tag::paren_sugar).decoder().decode(); - let trait_ref = doc_trait_ref(item_doc.get(item_tag::trait_ref), tcx, cdata); - let def_path = def_path(cdata, item_id).unwrap(); - ty::TraitDef::new(unsafety, paren_sugar, generics, trait_ref, - def_path.deterministic_hash(tcx)) + let data = match entry_data(item_doc, cdata) { + EntryData::Trait(data) => data, + _ => bug!() + }; + let typed_data = match entry_typed_data(item_doc, tcx, cdata) { + EntryTypedData::Trait(data) => data, + _ => bug!() + }; + + ty::TraitDef::new(data.unsafety, data.paren_sugar, generics, typed_data.trait_ref, + def_path(cdata, item_id).unwrap().deterministic_hash(tcx))) +} + +fn get_variant<'tcx>(cdata: Cmd, + item: rbml::Doc, + index: DefIndex) + -> (ty::VariantDefData<'tcx, 'tcx>, Option) { + let data = match entry_data(item, cdata) { + EntryData::Variant(data) => data, + _ => bug!() + }; + + let mut dcx = item.get(item_tag::children).decoder(); + dcx.cdata = Some(cdata); + + let fields = dcx.seq().map(|index| { + let f = cdata.lookup_item(index); + ty::FieldDefData::new(cdata.local_def_id(index), + item_name(f), + item_visibility(f)) + }).collect(); + + (ty::VariantDefData { + did: cdata.local_def_id(data.struct_ctor.unwrap_or(index)), + name: item_name(item), + fields: fields, + disr_val: ConstInt::Infer(data.disr), + kind: data.kind, + }, data.struct_ctor) } pub fn get_adt_def<'a, 'tcx>(cdata: Cmd, @@ -473,116 +502,47 @@ pub fn get_adt_def<'a, 'tcx>(cdata: Cmd, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ty::AdtDefMaster<'tcx> { - fn expect_variant_kind(family: Family) -> ty::VariantKind { - match family { - Struct(kind) | Variant(kind) => kind, - Union => ty::VariantKind::Struct, - _ => bug!("unexpected family: {:?}", family), - } - } - fn get_enum_variants<'tcx>(cdata: Cmd, doc: rbml::Doc) -> Vec> { + let doc = cdata.lookup_item(item_id); + let did = cdata.local_def_id(item_id); + let mut ctor_index = None; + let family = item_family(doc); + let variants = if family == Family::Enum { let mut dcx = doc.get(item_tag::children).decoder(); dcx.cdata = Some(cdata); - dcx.seq().map(|did: DefId| { - let item = cdata.lookup_item(did.index); - let disr = item.get(item_tag::disr_val).decoder().decode(); - ty::VariantDefData { - did: did, - name: item_name(item), - fields: get_variant_fields(cdata, item), - disr_val: ConstInt::Infer(disr), - kind: expect_variant_kind(item_family(item)), - } + dcx.seq().map(|index| { + let (variant, struct_ctor) = get_variant(cdata, cdata.lookup_item(index), index); + assert_eq!(struct_ctor, None); + variant }).collect() - } - fn get_variant_fields<'tcx>(cdata: Cmd, doc: rbml::Doc) -> Vec> { - let mut dcx = doc.get(item_tag::fields).decoder(); - dcx.cdata = Some(cdata); - - dcx.seq().map(|did: DefId| { - let f = cdata.lookup_item(did.index); - let vis = match item_family(f) { - PublicField => ty::Visibility::Public, - InheritedField => ty::Visibility::PrivateExternal, - _ => bug!() - }; - ty::FieldDefData::new(did, item_name(f), vis) - }).collect() - } - fn get_struct_variant<'tcx>(cdata: Cmd, - doc: rbml::Doc, - did: DefId) -> ty::VariantDefData<'tcx, 'tcx> { - ty::VariantDefData { - did: did, - name: item_name(doc), - fields: get_variant_fields(cdata, doc), - disr_val: ConstInt::Infer(0), - kind: expect_variant_kind(item_family(doc)), - } - } - - let doc = cdata.lookup_item(item_id); - let did = DefId { krate: cdata.cnum, index: item_id }; - let mut ctor_did = None; - let (kind, variants) = match item_family(doc) { - Enum => { - (AdtKind::Enum, get_enum_variants(cdata, doc)) - } - Struct(..) => { - // Use separate constructor id for unit/tuple structs and reuse did for braced structs. - ctor_did = reader::maybe_get_doc(doc, item_tag::struct_ctor).map(|ctor_doc| { - let mut dcx = ctor_doc.decoder(); - dcx.cdata = Some(cdata); - dcx.decode() - }); - (AdtKind::Struct, vec![get_struct_variant(cdata, doc, ctor_did.unwrap_or(did))]) - } - Union => { - (AdtKind::Union, vec![get_struct_variant(cdata, doc, did)]) - } - _ => bug!("get_adt_def called on a non-ADT {:?} - {:?}", item_family(doc), did) + } else{ + let (variant, struct_ctor) = get_variant(cdata, doc, item_id); + ctor_index = struct_ctor; + vec![variant] + }; + let kind = match family { + Family::Enum => ty::AdtKind::Enum, + Family::Struct => ty::AdtKind::Struct, + Family::Union => ty::AdtKind::Union, + _ => bug!("get_adt_def called on a non-ADT {:?} - {:?}", + family, did) }; let adt = tcx.intern_adt_def(did, kind, variants); - if let Some(ctor_did) = ctor_did { + if let Some(ctor_index) = ctor_index { // Make adt definition available through constructor id as well. - tcx.insert_adt_def(ctor_did, adt); + tcx.insert_adt_def(cdata.local_def_id(ctor_index), adt); } // this needs to be done *after* the variant is interned, // to support recursive structures for variant in &adt.variants { - if variant.kind == ty::VariantKind::Tuple && adt.is_enum() { - // tuple-like enum variant fields aren't real items - get the types - // from the ctor. - debug!("evaluating the ctor-type of {:?}", - variant.name); - let ctor_ty = get_type(cdata, variant.did.index, tcx); - debug!("evaluating the ctor-type of {:?}.. {:?}", - variant.name, - ctor_ty); - let field_tys = match ctor_ty.sty { - ty::TyFnDef(.., &ty::BareFnTy { sig: ty::Binder(ty::FnSig { - ref inputs, .. - }), ..}) => { - // tuple-struct constructors don't have escaping regions - assert!(!inputs.has_escaping_regions()); - inputs - }, - _ => bug!("tuple-variant ctor is not an ADT") - }; - for (field, &ty) in variant.fields.iter().zip(field_tys.iter()) { - field.fulfill_ty(ty); - } - } else { - for field in &variant.fields { - debug!("evaluating the type of {:?}::{:?}", variant.name, field.name); - let ty = get_type(cdata, field.did.index, tcx); - field.fulfill_ty(ty); - debug!("evaluating the type of {:?}::{:?}: {:?}", - variant.name, field.name, ty); - } + for field in &variant.fields { + debug!("evaluating the type of {:?}::{:?}", variant.name, field.name); + let ty = get_type(cdata, field.did.index, tcx); + field.fulfill_ty(ty); + debug!("evaluating the type of {:?}::{:?}: {:?}", + variant.name, field.name, ty); } } @@ -641,24 +601,19 @@ pub fn get_visibility(cdata: Cmd, id: DefIndex) -> ty::Visibility { item_visibility(cdata.lookup_item(id)) } -pub fn get_parent_impl(cdata: Cmd, id: DefIndex) -> Option { - let item = cdata.lookup_item(id); - reader::maybe_get_doc(item, item_tag::parent_impl).map(|doc| { - let mut dcx = doc.decoder(); - dcx.cdata = Some(cdata); - dcx.decode() - }) +fn get_impl_data(cdata: Cmd, id: DefIndex) -> ImplData { + match entry_data(cdata.lookup_item(id), cdata) { + EntryData::Impl(data) => data, + _ => bug!() + } } -pub fn get_repr_attrs(cdata: Cmd, id: DefIndex) -> Vec { - let item = cdata.lookup_item(id); - reader::maybe_get_doc(item, item_tag::repr).map_or(vec![], |doc| { - doc.decoder().decode() - }) +pub fn get_parent_impl(cdata: Cmd, id: DefIndex) -> Option { + get_impl_data(cdata, id).parent_impl } pub fn get_impl_polarity(cdata: Cmd, id: DefIndex) -> hir::ImplPolarity { - cdata.lookup_item(id).get(item_tag::polarity).decoder().decode() + get_impl_data(cdata, id).polarity } pub fn get_custom_coerce_unsized_kind( @@ -666,10 +621,7 @@ pub fn get_custom_coerce_unsized_kind( id: DefIndex) -> Option { - let item_doc = cdata.lookup_item(id); - reader::maybe_get_doc(item_doc, item_tag::impl_coerce_unsized_kind).map(|kind_doc| { - kind_doc.decoder().decode() - }) + get_impl_data(cdata, id).coerce_unsized_kind } pub fn get_impl_trait<'a, 'tcx>(cdata: Cmd, @@ -677,10 +629,10 @@ pub fn get_impl_trait<'a, 'tcx>(cdata: Cmd, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option> { - let item_doc = cdata.lookup_item(id); - reader::maybe_get_doc(item_doc, item_tag::trait_ref).map(|tp| { - doc_trait_ref(tp, tcx, cdata) - }) + match entry_typed_data(cdata.lookup_item(id), tcx, cdata) { + EntryTypedData::Impl(data) => data.trait_ref, + _ => bug!() + } } /// Iterates over the language items in the given crate. @@ -691,8 +643,8 @@ pub fn get_lang_items(cdata: Cmd) -> Vec<(DefIndex, usize)> { /// Iterates over each child of the given item. pub fn each_child_of_item(cdata: Cmd, id: DefIndex, - mut get_crate_data: G, - mut callback: F) + mut get_crate_data: &mut G, + mut callback: &mut F) where F: FnMut(Def, ast::Name, ty::Visibility), G: FnMut(CrateNum) -> Rc, { @@ -709,31 +661,24 @@ pub fn each_child_of_item(cdata: Cmd, id: DefIndex, dcx.cdata = Some(cdata); // Iterate over all children. - for child_def_id in dcx.seq_mut::() { - // This item may be in yet another crate if it was the child of a - // reexport. - let crate_data = if child_def_id.krate == cdata.cnum { - None - } else { - Some(get_crate_data(child_def_id.krate)) - }; - let crate_data = match crate_data { - Some(ref cdata) => &**cdata, - None => cdata - }; - + for child_index in dcx.seq::() { // Get the item. - if let Some(child_item_doc) = crate_data.get_item(child_def_id.index) { + if let Some(child) = cdata.get_item(child_index) { // Hand off the item to the callback. - if let Some(def) = item_to_def(crate_data, child_item_doc, child_def_id) { - let child_name = item_name(child_item_doc); - let visibility = item_visibility(child_item_doc); - callback(def, child_name, visibility); + let family = item_family(child); + if let Family::ForeignMod = family { + each_child_of_item(cdata, child_index, get_crate_data, callback); + } else if let Some(def) = family.to_def(cdata.local_def_id(child_index)) { + callback(def, item_name(child), item_visibility(child)); } } } - for exp in dcx.seq_mut::() { + let reexports = match entry_data(item_doc, cdata) { + EntryData::Mod(data) => data.reexports, + _ => return + }; + for exp in reexports { // This reexport may be in yet another crate. let crate_data = if exp.def_id.krate == cdata.cnum { None @@ -746,9 +691,9 @@ pub fn each_child_of_item(cdata: Cmd, id: DefIndex, }; // Get the item. - if let Some(child_item_doc) = crate_data.get_item(exp.def_id.index) { + if let Some(child) = crate_data.get_item(exp.def_id.index) { // Hand off the item to the callback. - if let Some(def) = item_to_def(crate_data, child_item_doc, exp.def_id) { + if let Some(def) = item_family(child).to_def(exp.def_id) { // These items have a public visibility because they're part of // a public re-export. callback(def, exp.name, ty::Visibility::Public); @@ -757,62 +702,21 @@ pub fn each_child_of_item(cdata: Cmd, id: DefIndex, } } -pub fn get_item_name(cdata: Cmd, id: DefIndex) -> ast::Name { - item_name(cdata.lookup_item(id)) -} - pub fn maybe_get_item_name(cdata: Cmd, id: DefIndex) -> Option { maybe_item_name(cdata.lookup_item(id)) } -pub enum FoundAst<'ast> { - Found(&'ast InlinedItem), - FoundParent(DefId, &'ast hir::Item), - NotFound, -} - pub fn maybe_get_item_ast<'a, 'tcx>(cdata: Cmd, tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefIndex) - -> FoundAst<'tcx> { + -> Option<&'tcx InlinedItem> { debug!("Looking up item: {:?}", id); let item_doc = cdata.lookup_item(id); - let item_did = item_def_id(item_doc, cdata); - let parent_def_id = DefId { - krate: cdata.cnum, - index: def_key(cdata, id).parent.unwrap() - }; + let item_did = cdata.local_def_id(id); + let parent_def_id = cdata.local_def_id(def_key(cdata, id).parent.unwrap()); let mut parent_def_path = def_path(cdata, id).unwrap(); parent_def_path.data.pop(); - if let Some(ast_doc) = reader::maybe_get_doc(item_doc, item_tag::ast as usize) { - let ii = decode_inlined_item(cdata, - tcx, - parent_def_path, - parent_def_id, - ast_doc, - item_did); - return FoundAst::Found(ii); - } else if let Some(parent_did) = item_parent_item(cdata, item_doc) { - // Remove the last element from the paths, since we are now - // trying to inline the parent. - let grandparent_def_id = DefId { - krate: cdata.cnum, - index: def_key(cdata, parent_def_id.index).parent.unwrap() - }; - let mut grandparent_def_path = parent_def_path; - grandparent_def_path.data.pop(); - let parent_doc = cdata.lookup_item(parent_did.index); - if let Some(ast_doc) = reader::maybe_get_doc(parent_doc, item_tag::ast as usize) { - let ii = decode_inlined_item(cdata, - tcx, - grandparent_def_path, - grandparent_def_id, - ast_doc, - parent_did); - if let &InlinedItem::Item(_, ref i) = ii { - return FoundAst::FoundParent(parent_did, i); - } - } - } - FoundAst::NotFound + reader::maybe_get_doc(item_doc, item_tag::ast).map(|ast_doc| { + decode_inlined_item(cdata, tcx, parent_def_path, parent_def_id, ast_doc, item_did) + }) } pub fn is_item_mir_available<'tcx>(cdata: Cmd, id: DefIndex) -> bool { @@ -837,41 +741,41 @@ pub fn maybe_get_item_mir<'a, 'tcx>(cdata: Cmd, }) } -fn get_explicit_self<'a, 'tcx>(cdata: Cmd, item: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>) - -> ty::ExplicitSelfCategory<'tcx> { - let mut dcx = item.get(item_tag::trait_method_explicit_self).decoder(); - dcx.cdata = Some(cdata); - dcx.tcx = Some(tcx); - - dcx.decode() -} - -pub fn get_trait_name(cdata: Cmd, id: DefIndex) -> ast::Name { - let doc = cdata.lookup_item(id); - item_name(doc) -} - pub fn get_impl_or_trait_item<'a, 'tcx>(cdata: Cmd, id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option> { let item_doc = cdata.lookup_item(id); + let family = item_family(item_doc); - let def_id = item_def_id(item_doc, cdata); + match family { + Family::AssociatedConst | + Family::Method | + Family::AssociatedType => {} - let container_id = if let Some(id) = item_parent_item(cdata, item_doc) { - id - } else { - return None; - }; + _ => return None + } + + let def_id = cdata.local_def_id(id); + + let container_id = item_parent_item(cdata, item_doc).unwrap(); let container = match item_family(cdata.lookup_item(container_id.index)) { - Trait => TraitContainer(container_id), + Family::Trait => TraitContainer(container_id), _ => ImplContainer(container_id), }; let name = item_name(item_doc); let vis = item_visibility(item_doc); - let defaultness = item_defaultness(item_doc); - Some(match item_family(item_doc) { + let (defaultness, has_body) = match entry_data(item_doc, cdata) { + EntryData::TraitAssociated(data) => { + (hir::Defaultness::Default, data.has_default) + } + EntryData::ImplAssociated(data) => { + (data.defaultness, true) + } + _ => bug!() + }; + + Some(match family { Family::AssociatedConst => { let ty = doc_type(item_doc, tcx, cdata); ty::ConstTraitItem(Rc::new(ty::AssociatedConst { @@ -881,7 +785,7 @@ pub fn get_impl_or_trait_item<'a, 'tcx>(cdata: Cmd, id: DefIndex, tcx: TyCtxt<'a defaultness: defaultness, def_id: def_id, container: container, - has_value: item_doc.get(item_tag::trait_item_has_body).decoder().decode(), + has_value: has_body, })) } Family::Method => { @@ -894,8 +798,11 @@ pub fn get_impl_or_trait_item<'a, 'tcx>(cdata: Cmd, id: DefIndex, tcx: TyCtxt<'a "the type {:?} of the method {:?} is not a function?", ity, name) }; - let explicit_self = get_explicit_self(cdata, item_doc, tcx); + let explicit_self = match entry_typed_data(item_doc, tcx, cdata) { + EntryTypedData::Method(data) => data.explicit_self, + _ => bug!() + }; ty::MethodTraitItem(Rc::new(ty::Method { name: name, generics: generics, @@ -904,7 +811,7 @@ pub fn get_impl_or_trait_item<'a, 'tcx>(cdata: Cmd, id: DefIndex, tcx: TyCtxt<'a explicit_self: explicit_self, vis: vis, defaultness: defaultness, - has_body: item_doc.get(item_tag::trait_item_has_body).decoder().decode(), + has_body: has_body, def_id: def_id, container: container, })) @@ -920,7 +827,7 @@ pub fn get_impl_or_trait_item<'a, 'tcx>(cdata: Cmd, id: DefIndex, tcx: TyCtxt<'a container: container, })) } - _ => return None + _ => bug!() }) } @@ -931,49 +838,33 @@ pub fn get_item_variances(cdata: Cmd, id: DefIndex) -> Vec { pub fn get_struct_ctor_def_id(cdata: Cmd, node_id: DefIndex) -> Option { - let item = cdata.lookup_item(node_id); - reader::maybe_get_doc(item, item_tag::struct_ctor).map(|ctor_doc| { - let mut dcx = ctor_doc.decoder(); - dcx.cdata = Some(cdata); - dcx.decode() - }) -} + let data = match entry_data(cdata.lookup_item(node_id), cdata) { + EntryData::Variant(data) => data, + _ => bug!() + }; -/// If node_id is the constructor of a tuple struct, retrieve the NodeId of -/// the actual type definition, otherwise, return None -pub fn get_tuple_struct_definition_if_ctor(cdata: Cmd, - node_id: DefIndex) - -> Option -{ - let item = cdata.lookup_item(node_id); - reader::maybe_get_doc(item, item_tag::is_tuple_struct_ctor).and_then(|doc| { - if doc.decoder().decode() { - Some(item_require_parent_item(cdata, item)) - } else { - None - } - }) + data.struct_ctor.map(|index| cdata.local_def_id(index)) } pub fn get_item_attrs(cdata: Cmd, - orig_node_id: DefIndex) + node_id: DefIndex) -> Vec { // The attributes for a tuple struct are attached to the definition, not the ctor; // we assume that someone passing in a tuple struct ctor is actually wanting to // look at the definition - let node_id = get_tuple_struct_definition_if_ctor(cdata, orig_node_id); - let node_id = node_id.map(|x| x.index).unwrap_or(orig_node_id); - let item = cdata.lookup_item(node_id); + let mut item = cdata.lookup_item(node_id); + let def_key = item_def_key(item); + if def_key.disambiguated_data.data == DefPathData::StructCtor { + item = cdata.lookup_item(def_key.parent.unwrap()); + } get_attributes(item) } pub fn get_struct_field_names(cdata: Cmd, id: DefIndex) -> Vec { - let mut dcx = cdata.lookup_item(id).get(item_tag::fields).decoder(); + let mut dcx = cdata.lookup_item(id).get(item_tag::children).decoder(); dcx.cdata = Some(cdata); - dcx.seq().map(|did: DefId| { - item_name(cdata.lookup_item(did.index)) - }).collect() + dcx.seq().map(|index| item_name(cdata.lookup_item(index))).collect() } fn get_attributes(md: rbml::Doc) -> Vec { @@ -1019,36 +910,8 @@ fn list_crate_deps(data: &[u8], out: &mut io::Write) -> io::Result<()> { Ok(()) } -pub fn maybe_get_crate_hash(data: &[u8]) -> Option { - let cratedoc = rbml::Doc::new(data); - reader::maybe_get_doc(cratedoc, root_tag::crate_hash).map(|doc| { - doc.decoder().decode() - }) -} - -pub fn get_crate_hash(data: &[u8]) -> Svh { - rbml::Doc::new(data).get(root_tag::crate_hash).decoder().decode() -} - -pub fn maybe_get_crate_name(data: &[u8]) -> Option { - let cratedoc = rbml::Doc::new(data); - reader::maybe_get_doc(cratedoc, root_tag::crate_crate_name).map(|doc| { - doc.decoder().decode() - }) -} - -pub fn get_crate_disambiguator(data: &[u8]) -> String { - rbml::Doc::new(data).get(root_tag::crate_disambiguator).decoder().decode() -} - -pub fn get_crate_triple(data: &[u8]) -> Option { - let cratedoc = rbml::Doc::new(data); - let triple_doc = reader::maybe_get_doc(cratedoc, root_tag::crate_triple); - triple_doc.map(|s| s.decoder().decode()) -} - -pub fn get_crate_name(data: &[u8]) -> String { - maybe_get_crate_name(data).expect("no crate name in crate") +pub fn get_crate_info(data: &[u8]) -> CrateInfo { + rbml::Doc::new(data).get(root_tag::crate_info).decoder().decode() } pub fn list_crate_metadata(bytes: &[u8], out: &mut io::Write) -> io::Result<()> { @@ -1118,9 +981,8 @@ pub fn get_trait_of_item(cdata: Cmd, id: DefIndex) -> Option { None => return None, Some(item_id) => item_id, }; - let parent_item_doc = cdata.lookup_item(parent_item_id.index); - match item_family(parent_item_doc) { - Trait => Some(item_def_id(parent_item_doc, cdata)), + match item_family(cdata.lookup_item(parent_item_id.index)) { + Family::Trait => Some(parent_item_id), _ => None } } @@ -1131,11 +993,6 @@ pub fn get_native_libraries(cdata: Cmd) rbml::Doc::new(cdata.data()).get(root_tag::native_libraries).decoder().decode() } -pub fn get_plugin_registrar_fn(data: &[u8]) -> Option { - reader::maybe_get_doc(rbml::Doc::new(data), root_tag::plugin_registrar_fn) - .map(|doc| doc.decoder().decode()) -} - pub fn each_exported_macro(data: &[u8], mut f: F) where F: FnMut(ast::Name, Vec, Span, String) -> bool, { @@ -1147,11 +1004,6 @@ pub fn each_exported_macro(data: &[u8], mut f: F) where } } -pub fn get_derive_registrar_fn(data: &[u8]) -> Option { - reader::maybe_get_doc(rbml::Doc::new(data), root_tag::macro_derive_registrar) - .map(|doc| doc.decoder().decode()) -} - pub fn get_dylib_dependency_formats(cdata: Cmd) -> Vec<(CrateNum, LinkagePreference)> { @@ -1167,9 +1019,9 @@ pub fn get_missing_lang_items(cdata: Cmd) -> Vec { rbml::Doc::new(cdata.data()).get(root_tag::lang_items_missing).decoder().decode() } -pub fn get_method_arg_names(cdata: Cmd, id: DefIndex) -> Vec { +pub fn get_fn_arg_names(cdata: Cmd, id: DefIndex) -> Vec { let method_doc = cdata.lookup_item(id); - match reader::maybe_get_doc(method_doc, item_tag::method_argument_names) { + match reader::maybe_get_doc(method_doc, item_tag::fn_arg_names) { Some(args_doc) => args_doc.decoder().decode(), None => vec![], } @@ -1178,24 +1030,16 @@ pub fn get_method_arg_names(cdata: Cmd, id: DefIndex) -> Vec { pub fn get_reachable_ids(cdata: Cmd) -> Vec { let dcx = rbml::Doc::new(cdata.data()).get(root_tag::reachable_ids).decoder(); - dcx.seq().map(|index| { - DefId { - krate: cdata.cnum, - index: index, - } - }).collect() + dcx.seq().map(|index| cdata.local_def_id(index)).collect() } pub fn is_const_fn(cdata: Cmd, id: DefIndex) -> bool { - match reader::maybe_get_doc(cdata.lookup_item(id), item_tag::constness) { - None => false, - Some(doc) => { - match doc.decoder().decode() { - hir::Constness::Const => true, - hir::Constness::NotConst => false, - } - } - } + let constness = match entry_data(cdata.lookup_item(id), cdata) { + EntryData::ImplAssociated(data) => data.constness, + EntryData::Fn(data) => data.constness, + _ => hir::Constness::NotConst + }; + constness == hir::Constness::Const } pub fn is_extern_item<'a, 'tcx>(cdata: Cmd, @@ -1207,8 +1051,15 @@ pub fn is_extern_item<'a, 'tcx>(cdata: Cmd, None => return false, }; let applicable = match item_family(item_doc) { - ImmStatic | MutStatic => true, - Fn => get_generics(cdata, id, tcx).types.is_empty(), + Family::ImmStatic | + Family::MutStatic | + Family::ForeignImmStatic | + Family::ForeignMutStatic => true, + + Family::Fn | Family::ForeignFn => { + get_generics(cdata, id, tcx).types.is_empty() + } + _ => false, }; @@ -1221,13 +1072,12 @@ pub fn is_extern_item<'a, 'tcx>(cdata: Cmd, } pub fn is_foreign_item(cdata: Cmd, id: DefIndex) -> bool { - let item_doc = cdata.lookup_item(id); - let parent_item_id = match item_parent_item(cdata, item_doc) { - None => return false, - Some(item_id) => item_id, - }; - let parent_item_doc = cdata.lookup_item(parent_item_id.index); - item_family(parent_item_doc) == ForeignMod + match item_family(cdata.lookup_item(id)) { + Family::ForeignImmStatic | + Family::ForeignMutStatic | + Family::ForeignFn => true, + _ => false + } } fn doc_generics<'a, 'tcx>(base_doc: rbml::Doc, @@ -1268,7 +1118,10 @@ fn doc_predicates<'a, 'tcx>(base_doc: rbml::Doc, } pub fn is_defaulted_trait(cdata: Cmd, trait_id: DefIndex) -> bool { - cdata.lookup_item(trait_id).get(item_tag::defaulted_trait).decoder().decode() + match entry_data(cdata.lookup_item(trait_id), cdata) { + EntryData::Trait(data) => data.has_default_impl, + _ => bug!() + } } pub fn is_default_impl(cdata: Cmd, impl_id: DefIndex) -> bool { @@ -1280,29 +1133,27 @@ pub fn get_imported_filemaps(metadata: &[u8]) -> Vec { } pub fn closure_kind(cdata: Cmd, closure_id: DefIndex) -> ty::ClosureKind { - cdata.lookup_item(closure_id).get(item_tag::closure_kind).decoder().decode() + match entry_data(cdata.lookup_item(closure_id), cdata) { + EntryData::Closure(data) => data.kind, + _ => bug!() + } } pub fn closure_ty<'a, 'tcx>(cdata: Cmd, closure_id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ty::ClosureTy<'tcx> { - let closure_doc = cdata.lookup_item(closure_id); - let closure_ty_doc = closure_doc.get(item_tag::closure_ty); - let mut dcx = closure_ty_doc.decoder(); - dcx.tcx = Some(tcx); - dcx.cdata = Some(cdata); - dcx.decode() + match entry_typed_data(cdata.lookup_item(closure_id), tcx, cdata) { + EntryTypedData::Closure(data) => data.ty, + _ => bug!() + } } pub fn def_key(cdata: Cmd, id: DefIndex) -> hir_map::DefKey { debug!("def_key: id={:?}", id); - let item_doc = cdata.lookup_item(id); - item_def_key(item_doc) + item_def_key(cdata.lookup_item(id)) } fn item_def_key(item_doc: rbml::Doc) -> hir_map::DefKey { - let simple_key = item_doc.get(item_tag::def_key).decoder().decode(); - let name = maybe_item_name(item_doc).map(|name| name.as_str()); - def_key::recover_def_key(simple_key, name) + item_doc.get(item_tag::def_key).decoder().decode() } // Returns the path leading to the thing with this `id`. Note that @@ -1316,7 +1167,3 @@ pub fn def_path(cdata: Cmd, id: DefIndex) -> Option { None } } - -pub fn get_panic_strategy(data: &[u8]) -> PanicStrategy { - rbml::Doc::new(data).get(root_tag::panic_strategy).decoder().decode() -} diff --git a/src/librustc_metadata/def_key.rs b/src/librustc_metadata/def_key.rs deleted file mode 100644 index 285ca2e4d4d4d..0000000000000 --- a/src/librustc_metadata/def_key.rs +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use rustc::hir::def_id::DefIndex; -use rustc::hir::map as hir_map; -use syntax::parse::token::InternedString; - -#[derive(RustcEncodable, RustcDecodable)] -pub struct DefKey { - pub parent: Option, - pub disambiguated_data: DisambiguatedDefPathData, -} - -#[derive(RustcEncodable, RustcDecodable)] -pub struct DisambiguatedDefPathData { - pub data: DefPathData, - pub disambiguator: u32, -} - -#[derive(RustcEncodable, RustcDecodable)] -pub enum DefPathData { - CrateRoot, - Misc, - Impl, - TypeNs, - ValueNs, - Module, - MacroDef, - ClosureExpr, - TypeParam, - LifetimeDef, - EnumVariant, - Field, - StructCtor, - Initializer, - Binding, - ImplTrait, -} - -pub fn simplify_def_key(key: hir_map::DefKey) -> DefKey { - let data = DisambiguatedDefPathData { - data: simplify_def_path_data(key.disambiguated_data.data), - disambiguator: key.disambiguated_data.disambiguator, - }; - DefKey { - parent: key.parent, - disambiguated_data: data, - } -} - -fn simplify_def_path_data(data: hir_map::DefPathData) -> DefPathData { - match data { - hir_map::DefPathData::CrateRoot => DefPathData::CrateRoot, - hir_map::DefPathData::InlinedRoot(_) => bug!("unexpected DefPathData"), - hir_map::DefPathData::Misc => DefPathData::Misc, - hir_map::DefPathData::Impl => DefPathData::Impl, - hir_map::DefPathData::TypeNs(_) => DefPathData::TypeNs, - hir_map::DefPathData::ValueNs(_) => DefPathData::ValueNs, - hir_map::DefPathData::Module(_) => DefPathData::Module, - hir_map::DefPathData::MacroDef(_) => DefPathData::MacroDef, - hir_map::DefPathData::ClosureExpr => DefPathData::ClosureExpr, - hir_map::DefPathData::TypeParam(_) => DefPathData::TypeParam, - hir_map::DefPathData::LifetimeDef(_) => DefPathData::LifetimeDef, - hir_map::DefPathData::EnumVariant(_) => DefPathData::EnumVariant, - hir_map::DefPathData::Field(_) => DefPathData::Field, - hir_map::DefPathData::StructCtor => DefPathData::StructCtor, - hir_map::DefPathData::Initializer => DefPathData::Initializer, - hir_map::DefPathData::Binding(_) => DefPathData::Binding, - hir_map::DefPathData::ImplTrait => DefPathData::ImplTrait, - } -} - -pub fn recover_def_key(key: DefKey, name: Option) -> hir_map::DefKey { - let data = hir_map::DisambiguatedDefPathData { - data: recover_def_path_data(key.disambiguated_data.data, name), - disambiguator: key.disambiguated_data.disambiguator, - }; - hir_map::DefKey { - parent: key.parent, - disambiguated_data: data, - } -} - -fn recover_def_path_data(data: DefPathData, name: Option) -> hir_map::DefPathData { - match data { - DefPathData::CrateRoot => hir_map::DefPathData::CrateRoot, - DefPathData::Misc => hir_map::DefPathData::Misc, - DefPathData::Impl => hir_map::DefPathData::Impl, - DefPathData::TypeNs => hir_map::DefPathData::TypeNs(name.unwrap()), - DefPathData::ValueNs => hir_map::DefPathData::ValueNs(name.unwrap()), - DefPathData::Module => hir_map::DefPathData::Module(name.unwrap()), - DefPathData::MacroDef => hir_map::DefPathData::MacroDef(name.unwrap()), - DefPathData::ClosureExpr => hir_map::DefPathData::ClosureExpr, - DefPathData::TypeParam => hir_map::DefPathData::TypeParam(name.unwrap()), - DefPathData::LifetimeDef => hir_map::DefPathData::LifetimeDef(name.unwrap()), - DefPathData::EnumVariant => hir_map::DefPathData::EnumVariant(name.unwrap()), - DefPathData::Field => hir_map::DefPathData::Field(name.unwrap()), - DefPathData::StructCtor => hir_map::DefPathData::StructCtor, - DefPathData::Initializer => hir_map::DefPathData::Initializer, - DefPathData::Binding => hir_map::DefPathData::Binding(name.unwrap()), - DefPathData::ImplTrait => hir_map::DefPathData::ImplTrait, - } -} diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 1e4c61e0b2e10..3ad9251b07216 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -16,15 +16,12 @@ use astencode::encode_inlined_item; use common::*; use cstore; -use decoder; -use def_key; use index::{self, IndexData}; -use middle::cstore::{InlinedItemRef, LinkMeta, LinkagePreference}; +use rustc::middle::cstore::{InlinedItemRef, LinkMeta, LinkagePreference}; use rustc::hir::def; -use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId}; -use middle::dependency_format::Linkage; -use rustc::dep_graph::DepNode; +use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId}; +use rustc::middle::dependency_format::Linkage; use rustc::traits::specialization_graph; use rustc::ty::{self, Ty, TyCtxt}; @@ -41,7 +38,7 @@ use std::mem; use std::ops::{Deref, DerefMut}; use std::rc::Rc; use std::u32; -use syntax::ast::{self, NodeId, Name, CRATE_NODE_ID}; +use syntax::ast::{self, CRATE_NODE_ID}; use syntax::attr; use syntax; use rbml; @@ -49,7 +46,6 @@ use rbml; use rustc::hir::{self, PatKind}; use rustc::hir::intravisit::Visitor; use rustc::hir::intravisit; -use rustc::hir::map::DefKey; use super::index_builder::{FromId, IndexBuilder, Untracked}; @@ -166,59 +162,29 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { Ok(()) }).unwrap(); } -} - -fn encode_name(ecx: &mut EncodeContext, name: Name) { - ecx.start_tag(item_tag::name); - name.encode(ecx).unwrap(); - ecx.end_tag(); -} - -fn encode_def_id(ecx: &mut EncodeContext, def_id: DefId) { - assert!(def_id.is_local()); - ecx.start_tag(item_tag::def_index); - def_id.index.encode(ecx).unwrap(); - ecx.end_tag(); -} - -fn encode_def_key(ecx: &mut EncodeContext, key: DefKey) { - let simple_key = def_key::simplify_def_key(key); - ecx.start_tag(item_tag::def_key); - simple_key.encode(ecx); - ecx.end_tag(); -} - -/// For every DefId that we create a metadata item for, we include a -/// serialized copy of its DefKey, which allows us to recreate a path. -fn encode_def_id_and_key(ecx: &mut EncodeContext, def_id: DefId) { - encode_def_id(ecx, def_id); - let def_key = ecx.tcx.map.def_key(def_id); - encode_def_key(ecx, def_key); -} -fn encode_trait_ref<'a, 'tcx>(ecx: &mut EncodeContext<'a, 'tcx>, - trait_ref: ty::TraitRef<'tcx>, - tag: usize) { - ecx.start_tag(tag); - trait_ref.encode(ecx).unwrap(); - ecx.end_tag(); -} + /// For every DefId that we create a metadata item for, we include a + /// serialized copy of its DefKey, which allows us to recreate a path. + fn encode_def_key(&mut self, def_id: DefId) { + self.start_tag(item_tag::def_key); + self.tcx.map.def_key(def_id).encode(self); + self.end_tag(); + } -// Item info table encoding -fn encode_family(ecx: &mut EncodeContext, f: Family) { - ecx.start_tag(item_tag::family); - f.encode(ecx).unwrap(); - ecx.end_tag(); -} + // Item info table encoding + fn encode_family(&mut self, f: Family) { + self.start_tag(item_tag::family); + f.encode(self).unwrap(); + self.end_tag(); + } -fn encode_item_variances(ecx: &mut EncodeContext, id: NodeId) { - let v = ecx.tcx.item_variances(ecx.tcx.map.local_def_id(id)); - ecx.start_tag(item_tag::variances); - v.encode(ecx); - ecx.end_tag(); -} + fn encode_item_variances(&mut self, def_id: DefId) { + let v = self.tcx.item_variances(def_id); + self.start_tag(item_tag::variances); + v.encode(self); + self.end_tag(); + } -impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn encode_bounds_and_type_for_item(&mut self, def_id: DefId) { let tcx = self.tcx; self.encode_bounds_and_type(&tcx.lookup_item_type(def_id), @@ -238,37 +204,21 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.end_tag(); } - fn encode_disr_val(&mut self, - disr_val: ty::Disr) { - self.start_tag(item_tag::disr_val); - disr_val.to_u64_unchecked().encode(self).unwrap(); - self.end_tag(); - } - - fn encode_parent_item(&mut self, id: DefId) { - self.start_tag(item_tag::parent_item); - id.encode(self).unwrap(); - self.end_tag(); - } - - fn encode_variant_fields(&mut self, - variant: ty::VariantDef) { - self.start_tag(item_tag::fields); - self.seq(&variant.fields, |_, f| f.did); + fn encode_variant(&mut self, variant: ty::VariantDef, + struct_ctor: Option) + -> EntryData { + self.start_tag(item_tag::children); + self.seq(&variant.fields, |_, f| { + assert!(f.did.is_local()); + f.did.index + }); self.end_tag(); - } -} -impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { - fn encode_enum_variant_infos(&mut self, enum_did: DefId) { - debug!("encode_enum_variant_info(enum_did={:?})", enum_did); - let def = self.tcx.lookup_adt_def(enum_did); - self.encode_fields(enum_did); - for (i, variant) in def.variants.iter().enumerate() { - self.record(variant.did, - EncodeContext::encode_enum_variant_info, - (enum_did, Untracked(i))); - } + EntryData::Variant(VariantData { + kind: variant.kind, + disr: variant.disr_val.to_u64_unchecked(), + struct_ctor: struct_ctor + }) } } @@ -285,10 +235,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let def = tcx.lookup_adt_def(enum_did); let variant = &def.variants[index]; let vid = variant.did; - encode_def_id_and_key(self, vid); - encode_family(self, Family::Variant(variant.kind)); - encode_name(self, variant.name); - self.encode_parent_item(enum_did); + self.encode_def_key(vid); + self.encode_family(Family::Variant); let enum_id = tcx.map.as_local_node_id(enum_did).unwrap(); let enum_vis = &tcx.map.expect_item(enum_id).vis; @@ -296,60 +244,58 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let attrs = tcx.get_attrs(vid); encode_attributes(self, &attrs); - self.encode_repr_attrs(&attrs); + encode_stability(self, vid); + + let data = self.encode_variant(variant, None); + + self.start_tag(item_tag::data); + data.encode(self).unwrap(); + self.end_tag(); - let stab = tcx.lookup_stability(vid); - let depr = tcx.lookup_deprecation(vid); - encode_stability(self, stab); - encode_deprecation(self, depr); + self.start_tag(item_tag::typed_data); + EntryTypedData::Other.encode(self).unwrap(); + self.end_tag(); - self.encode_variant_fields(variant); - self.encode_disr_val(variant.disr_val); self.encode_bounds_and_type_for_item(vid); } } impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn encode_info_for_mod(&mut self, - FromId(id, (md, attrs, name, vis)): - FromId<(&hir::Mod, &[ast::Attribute], Name, &hir::Visibility)>) { + FromId(id, (md, attrs, vis)): + FromId<(&hir::Mod, &[ast::Attribute], &hir::Visibility)>) { let tcx = self.tcx; - encode_def_id_and_key(self, tcx.map.local_def_id(id)); - encode_family(self, Family::Mod); - encode_name(self, name); + let def_id = tcx.map.local_def_id(id); + self.encode_def_key(def_id); + self.encode_family(Family::Mod); + self.encode_visibility(vis); + encode_stability(self, def_id); + encode_attributes(self, attrs); debug!("(encoding info for module) encoding info for module ID {}", id); // Encode info about all the module children. self.start_tag(item_tag::children); self.seq(&md.item_ids, |_, item_id| { - tcx.map.local_def_id(item_id.id) + tcx.map.local_def_id(item_id.id).index }); - - // Encode the reexports of this module, if this module is public. - match self.reexports.get(&id) { - Some(exports) if *vis == hir::Public => exports.encode(self).unwrap(), - _ => <[def::Export]>::encode(&[], self).unwrap() - } self.end_tag(); - self.encode_visibility(vis); - - let stab = tcx.lookup_stability(tcx.map.local_def_id(id)); - let depr = tcx.lookup_deprecation(tcx.map.local_def_id(id)); - encode_stability(self, stab); - encode_deprecation(self, depr); + // Encode the reexports of this module, if this module is public. + let reexports = match self.reexports.get(&id) { + Some(exports) if *vis == hir::Public => exports.clone(), + _ => vec![] + }; - encode_attributes(self, attrs); - } + self.start_tag(item_tag::data); + EntryData::Mod(ModData { + reexports: reexports + }).encode(self).unwrap(); + self.end_tag(); - fn encode_struct_field_family(&mut self, - visibility: ty::Visibility) { - encode_family(self, if visibility.is_public() { - Family::PublicField - } else { - Family::InheritedField - }); + self.start_tag(item_tag::typed_data); + EntryTypedData::Other.encode(self).unwrap(); + self.end_tag(); } fn encode_visibility(&mut self, visibility: T) { @@ -380,18 +326,6 @@ impl HasVisibility for ty::Visibility { } } -fn encode_constness(ecx: &mut EncodeContext, constness: hir::Constness) { - ecx.start_tag(item_tag::constness); - constness.encode(ecx).unwrap(); - ecx.end_tag(); -} - -fn encode_defaultness(ecx: &mut EncodeContext, defaultness: hir::Defaultness) { - ecx.start_tag(item_tag::defaultness); - defaultness.encode(ecx).unwrap(); - ecx.end_tag(); -} - impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { fn encode_fields(&mut self, adt_def_id: DefId) { @@ -424,48 +358,23 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let nm = field.name; debug!("encode_field: encoding {} {:?}", nm, field.did); - self.encode_struct_field_family(field.vis); - encode_name(self, nm); + self.encode_family(Family::Field); + self.encode_visibility(field.vis); self.encode_bounds_and_type_for_item(field.did); - encode_def_id_and_key(self, field.did); + self.encode_def_key(field.did); let variant_id = tcx.map.as_local_node_id(variant.did).unwrap(); let variant_data = tcx.map.expect_variant_data(variant_id); encode_attributes(self, &variant_data.fields()[field_index].attrs); - - let stab = tcx.lookup_stability(field.did); - let depr = tcx.lookup_deprecation(field.did); - encode_stability(self, stab); - encode_deprecation(self, depr); + encode_stability(self, field.did); } - fn encode_struct_ctor(&mut self, - (struct_def_id, struct_node_id, ctor_node_id): - (DefId, ast::NodeId, ast::NodeId)) { - let tcx = self.tcx; - let def = tcx.lookup_adt_def(struct_def_id); - let variant = def.struct_variant(); - let item = tcx.map.expect_item(struct_node_id); - let ctor_def_id = tcx.map.local_def_id(ctor_node_id); - encode_def_id_and_key(self, ctor_def_id); - encode_family(self, Family::Struct(variant.kind)); + fn encode_struct_ctor(&mut self, ctor_def_id: DefId) { + self.encode_def_key(ctor_def_id); + self.encode_family(Family::Struct); self.encode_bounds_and_type_for_item(ctor_def_id); - encode_name(self, item.name); - self.encode_parent_item(struct_def_id); - - let stab = tcx.lookup_stability(ctor_def_id); - let depr = tcx.lookup_deprecation(ctor_def_id); - encode_stability(self, stab); - encode_deprecation(self, depr); - - // indicate that this is a tuple struct ctor, because - // downstream users will normally want the tuple struct - // definition, but without this there is no way for them - // to tell that they actually have a ctor rather than a - // normal function - self.start_tag(item_tag::is_tuple_struct_ctor); - true.encode(self).unwrap(); - self.end_tag(); + + encode_stability(self, ctor_def_id); } fn encode_generics(&mut self, @@ -489,215 +398,137 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.end_tag(); } - fn encode_method_ty_fields(&mut self, method_ty: &ty::Method<'tcx>) { - encode_def_id_and_key(self, method_ty.def_id); - encode_name(self, method_ty.name); - self.encode_generics(&method_ty.generics, &method_ty.predicates); - self.encode_visibility(method_ty.vis); - - self.start_tag(item_tag::trait_method_explicit_self); - method_ty.explicit_self.encode(self).unwrap(); - self.end_tag(); - - encode_family(self, Family::Method); - } - - fn encode_info_for_trait_item(&mut self, - (trait_def_id, item_def_id, trait_item): - (DefId, DefId, &hir::TraitItem)) { + fn encode_info_for_trait_item(&mut self, def_id: DefId) { let tcx = self.tcx; - self.encode_parent_item(trait_def_id); - - let stab = tcx.lookup_stability(item_def_id); - let depr = tcx.lookup_deprecation(item_def_id); - encode_stability(self, stab); - encode_deprecation(self, depr); + let node_id = tcx.map.as_local_node_id(def_id).unwrap(); + let ast_item = tcx.map.expect_trait_item(node_id); + let trait_item = tcx.impl_or_trait_item(def_id); + let (family, has_default, typed_data) = match trait_item { + ty::ConstTraitItem(ref associated_const) => { + self.encode_bounds_and_type_for_item(def_id); - match tcx.impl_or_trait_item(item_def_id) { - ty::ConstTraitItem(associated_const) => { - encode_name(self, associated_const.name); - encode_def_id_and_key(self, item_def_id); - self.encode_visibility(associated_const.vis); + let trait_def_id = trait_item.container().id(); + encode_inlined_item(self, + InlinedItemRef::TraitItem(trait_def_id, ast_item)); - encode_family(self, Family::AssociatedConst); - self.encode_bounds_and_type_for_item(item_def_id); + (Family::AssociatedConst, + associated_const.has_value, + EntryTypedData::Other) } - ty::MethodTraitItem(method_ty) => { - self.encode_method_ty_fields(&method_ty); - self.encode_bounds_and_type_for_item(item_def_id); - } - ty::TypeTraitItem(associated_type) => { - encode_name(self, associated_type.name); - encode_def_id_and_key(self, item_def_id); - encode_family(self, Family::AssociatedType); + ty::MethodTraitItem(ref method_ty) => { + self.encode_bounds_and_type_for_item(def_id); + (Family::Method, + method_ty.has_body, + EntryTypedData::Method(MethodTypedData { + explicit_self: method_ty.explicit_self + })) + } + ty::TypeTraitItem(ref associated_type) => { if let Some(ty) = associated_type.ty { self.encode_type(ty); } + + (Family::AssociatedType, false, EntryTypedData::Other) } - } + }; - encode_attributes(self, &trait_item.attrs); - match trait_item.node { - hir::ConstTraitItem(_, ref default) => { - self.start_tag(item_tag::trait_item_has_body); - default.is_some().encode(self).unwrap(); - self.end_tag(); + self.encode_def_key(def_id); + self.encode_family(family); + self.encode_visibility(trait_item.vis()); - encode_inlined_item(self, - InlinedItemRef::TraitItem(trait_def_id, trait_item)); - self.encode_mir(item_def_id); - } - hir::MethodTraitItem(ref sig, ref body) => { - self.start_tag(item_tag::trait_item_has_body); - body.is_some().encode(self).unwrap(); - self.end_tag(); + encode_stability(self, def_id); + encode_attributes(self, &ast_item.attrs); + if let hir::MethodTraitItem(ref sig, _) = ast_item.node { + self.encode_fn_arg_names(&sig.decl); + }; - self.encode_mir(item_def_id); - self.encode_method_argument_names(&sig.decl); - } + self.start_tag(item_tag::data); + EntryData::TraitAssociated(TraitAssociatedData { + has_default: has_default + }).encode(self).unwrap(); + self.end_tag(); - hir::TypeTraitItem(..) => {} - } + self.start_tag(item_tag::typed_data); + typed_data.encode(self).unwrap(); + self.end_tag(); + + self.encode_mir(def_id); } - fn encode_info_for_impl_item(&mut self, - (impl_id, impl_item_def_id, ast_item): - (NodeId, DefId, Option<&hir::ImplItem>)) { - match self.tcx.impl_or_trait_item(impl_item_def_id) { - ty::ConstTraitItem(ref associated_const) => { - self.encode_info_for_associated_const(&associated_const, - impl_id, - ast_item) + fn encode_info_for_impl_item(&mut self, def_id: DefId) { + let node_id = self.tcx.map.as_local_node_id(def_id).unwrap(); + let ast_item = self.tcx.map.expect_impl_item(node_id); + let impl_item = self.tcx.impl_or_trait_item(def_id); + let impl_def_id = impl_item.container().id(); + let (family, typed_data) = match impl_item { + ty::ConstTraitItem(_) => { + self.encode_bounds_and_type_for_item(def_id); + + encode_inlined_item(self, + InlinedItemRef::ImplItem(impl_def_id, ast_item)); + self.encode_mir(def_id); + + (Family::AssociatedConst, EntryTypedData::Other) } ty::MethodTraitItem(ref method_type) => { - self.encode_info_for_method(&method_type, - impl_id, - ast_item) + self.encode_bounds_and_type_for_item(def_id); + + (Family::Method, + EntryTypedData::Method(MethodTypedData { + explicit_self: method_type.explicit_self + })) } ty::TypeTraitItem(ref associated_type) => { - self.encode_info_for_associated_type(&associated_type, - impl_id, - ast_item) - } - } - } + if let Some(ty) = associated_type.ty { + self.encode_type(ty); + } - fn encode_info_for_associated_const(&mut self, - associated_const: &ty::AssociatedConst, - parent_id: NodeId, - impl_item_opt: Option<&hir::ImplItem>) { - let tcx = self.tcx; - debug!("encode_info_for_associated_const({:?},{:?})", - associated_const.def_id, - associated_const.name); + (Family::AssociatedType, EntryTypedData::Other) + } + }; - encode_def_id_and_key(self, associated_const.def_id); - encode_name(self, associated_const.name); - self.encode_visibility(associated_const.vis); - encode_family(self, Family::AssociatedConst); + self.encode_def_key(def_id); + self.encode_family(family); + self.encode_visibility(impl_item.vis()); + encode_attributes(self, &ast_item.attrs); + encode_stability(self, def_id); + + let constness = if let hir::ImplItemKind::Method(ref sig, _) = ast_item.node { + if sig.constness == hir::Constness::Const { + encode_inlined_item( + self, + InlinedItemRef::ImplItem(impl_def_id, ast_item)); + } - self.encode_parent_item(tcx.map.local_def_id(parent_id)); + let generics = self.tcx.lookup_generics(def_id); + let types = generics.parent_types as usize + generics.types.len(); + let needs_inline = types > 0 || attr::requests_inline(&ast_item.attrs); + if needs_inline || sig.constness == hir::Constness::Const { + self.encode_mir(def_id); + } + self.encode_fn_arg_names(&sig.decl); + sig.constness + } else { + hir::Constness::NotConst + }; - self.start_tag(item_tag::trait_item_has_body); - true.encode(self).unwrap(); + self.start_tag(item_tag::data); + EntryData::ImplAssociated(ImplAssociatedData { + defaultness: ast_item.defaultness, + constness:constness + }).encode(self).unwrap(); self.end_tag(); - self.encode_bounds_and_type_for_item(associated_const.def_id); - - let stab = tcx.lookup_stability(associated_const.def_id); - let depr = tcx.lookup_deprecation(associated_const.def_id); - encode_stability(self, stab); - encode_deprecation(self, depr); - - if let Some(ii) = impl_item_opt { - encode_attributes(self, &ii.attrs); - encode_defaultness(self, ii.defaultness); - encode_inlined_item(self, - InlinedItemRef::ImplItem(tcx.map.local_def_id(parent_id), - ii)); - self.encode_mir(associated_const.def_id); - } - } - - fn encode_info_for_method(&mut self, - m: &ty::Method<'tcx>, - parent_id: NodeId, - impl_item_opt: Option<&hir::ImplItem>) { - let tcx = self.tcx; - - debug!("encode_info_for_method: {:?} {:?}", m.def_id, - m.name); - self.encode_method_ty_fields(m); - self.encode_parent_item(tcx.map.local_def_id(parent_id)); - - self.start_tag(item_tag::trait_item_has_body); - true.encode(self).unwrap(); + self.start_tag(item_tag::typed_data); + typed_data.encode(self).unwrap(); self.end_tag(); - - let stab = tcx.lookup_stability(m.def_id); - let depr = tcx.lookup_deprecation(m.def_id); - encode_stability(self, stab); - encode_deprecation(self, depr); - - self.encode_bounds_and_type_for_item(m.def_id); - - if let Some(impl_item) = impl_item_opt { - if let hir::ImplItemKind::Method(ref sig, _) = impl_item.node { - encode_attributes(self, &impl_item.attrs); - let generics = tcx.lookup_generics(m.def_id); - let types = generics.parent_types as usize + generics.types.len(); - let needs_inline = types > 0 || attr::requests_inline(&impl_item.attrs); - if sig.constness == hir::Constness::Const { - encode_inlined_item( - self, - InlinedItemRef::ImplItem(tcx.map.local_def_id(parent_id), - impl_item)); - } - if needs_inline || sig.constness == hir::Constness::Const { - self.encode_mir(m.def_id); - } - encode_constness(self, sig.constness); - encode_defaultness(self, impl_item.defaultness); - self.encode_method_argument_names(&sig.decl); - } - } - } - - fn encode_info_for_associated_type(&mut self, - associated_type: &ty::AssociatedType<'tcx>, - parent_id: NodeId, - impl_item_opt: Option<&hir::ImplItem>) { - let tcx = self.tcx; - debug!("encode_info_for_associated_type({:?},{:?})", - associated_type.def_id, - associated_type.name); - - encode_def_id_and_key(self, associated_type.def_id); - encode_name(self, associated_type.name); - self.encode_visibility(associated_type.vis); - encode_family(self, Family::AssociatedType); - self.encode_parent_item(tcx.map.local_def_id(parent_id)); - - let stab = tcx.lookup_stability(associated_type.def_id); - let depr = tcx.lookup_deprecation(associated_type.def_id); - encode_stability(self, stab); - encode_deprecation(self, depr); - - if let Some(ii) = impl_item_opt { - encode_attributes(self, &ii.attrs); - encode_defaultness(self, ii.defaultness); - } - - if let Some(ty) = associated_type.ty { - self.encode_type(ty); - } } - fn encode_method_argument_names(&mut self, + fn encode_fn_arg_names(&mut self, decl: &hir::FnDecl) { - self.start_tag(item_tag::method_argument_names); + self.start_tag(item_tag::fn_arg_names); self.seq(&decl.inputs, |_, arg| { if let PatKind::Binding(_, ref path1, _) = arg.pat.node { @@ -710,18 +541,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.end_tag(); } - fn encode_repr_attrs(&mut self, - attrs: &[ast::Attribute]) { - let mut repr_attrs = Vec::new(); - for attr in attrs { - repr_attrs.extend(attr::find_repr_attrs(self.tcx.sess.diagnostic(), - attr)); - } - self.start_tag(item_tag::repr); - repr_attrs.encode(self); - self.end_tag(); - } - fn encode_mir(&mut self, def_id: DefId) { if let Some(mir) = self.mir_map.map.get(&def_id) { self.start_tag(item_tag::mir as usize); @@ -742,16 +561,13 @@ fn encode_inherent_implementations(ecx: &mut EncodeContext, ecx.end_tag(); } -fn encode_stability(ecx: &mut EncodeContext, stab_opt: Option<&attr::Stability>) { - stab_opt.map(|stab| { +fn encode_stability(ecx: &mut EncodeContext, def_id: DefId) { + ecx.tcx.lookup_stability(def_id).map(|stab| { ecx.start_tag(item_tag::stability); stab.encode(ecx).unwrap(); ecx.end_tag(); }); -} - -fn encode_deprecation(ecx: &mut EncodeContext, depr_opt: Option) { - depr_opt.map(|depr| { + ecx.tcx.lookup_deprecation(def_id).map(|depr| { ecx.start_tag(item_tag::deprecation); depr.encode(ecx).unwrap(); ecx.end_tag(); @@ -794,47 +610,26 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { debug!("encoding info for item at {}", tcx.sess.codemap().span_to_string(item.span)); - let vis = &item.vis; - - let (stab, depr) = tcx.dep_graph.with_task(DepNode::MetaData(def_id), || { - (tcx.lookup_stability(tcx.map.local_def_id(item.id)), - tcx.lookup_deprecation(tcx.map.local_def_id(item.id))) - }); - - match item.node { + let (family, data, typed_data) = match item.node { hir::ItemStatic(_, m, _) => { - encode_def_id_and_key(self, def_id); - encode_family(self, if m == hir::MutMutable { - Family::MutStatic - } else { - Family::ImmStatic - }); self.encode_bounds_and_type_for_item(def_id); - encode_name(self, item.name); - self.encode_visibility(vis); - encode_stability(self, stab); - encode_deprecation(self, depr); - encode_attributes(self, &item.attrs); + + if m == hir::MutMutable { + (Family::MutStatic, EntryData::Other, EntryTypedData::Other) + } else { + (Family::ImmStatic, EntryData::Other, EntryTypedData::Other) + } } hir::ItemConst(..) => { - encode_def_id_and_key(self, def_id); - encode_family(self, Family::Const); self.encode_bounds_and_type_for_item(def_id); - encode_name(self, item.name); - encode_attributes(self, &item.attrs); encode_inlined_item(self, InlinedItemRef::Item(def_id, item)); self.encode_mir(def_id); - self.encode_visibility(vis); - encode_stability(self, stab); - encode_deprecation(self, depr); + + (Family::Const, EntryData::Other, EntryTypedData::Other) } hir::ItemFn(ref decl, _, constness, _, ref generics, _) => { - encode_def_id_and_key(self, def_id); - encode_family(self, Family::Fn); let tps_len = generics.ty_params.len(); self.encode_bounds_and_type_for_item(def_id); - encode_name(self, item.name); - encode_attributes(self, &item.attrs); let needs_inline = tps_len > 0 || attr::requests_inline(&item.attrs); if constness == hir::Constness::Const { encode_inlined_item(self, InlinedItemRef::Item(def_id, item)); @@ -842,224 +637,172 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { if needs_inline || constness == hir::Constness::Const { self.encode_mir(def_id); } - encode_constness(self, constness); - self.encode_visibility(vis); - encode_stability(self, stab); - encode_deprecation(self, depr); - self.encode_method_argument_names(&decl); + self.encode_fn_arg_names(&decl); + + (Family::Fn, EntryData::Fn(FnData { + constness: constness + }), EntryTypedData::Other) } hir::ItemMod(ref m) => { - self.encode_info_for_mod(FromId(item.id, (m, &item.attrs, item.name, &item.vis))); + self.encode_info_for_mod(FromId(item.id, (m, &item.attrs, &item.vis))); + return; } hir::ItemForeignMod(ref fm) => { - encode_def_id_and_key(self, def_id); - encode_family(self, Family::ForeignMod); - encode_name(self, item.name); - // Encode all the items in self module. self.start_tag(item_tag::children); self.seq(&fm.items, |_, foreign_item| { - tcx.map.local_def_id(foreign_item.id) + tcx.map.local_def_id(foreign_item.id).index }); - <[def::Export]>::encode(&[], self).unwrap(); self.end_tag(); - self.encode_visibility(vis); - encode_stability(self, stab); - encode_deprecation(self, depr); + (Family::ForeignMod, EntryData::Other, EntryTypedData::Other) } hir::ItemTy(..) => { - encode_def_id_and_key(self, def_id); - encode_family(self, Family::Type); self.encode_bounds_and_type_for_item(def_id); - encode_name(self, item.name); - self.encode_visibility(vis); - encode_stability(self, stab); - encode_deprecation(self, depr); + + (Family::Type, EntryData::Other, EntryTypedData::Other) } hir::ItemEnum(ref enum_definition, _) => { - encode_def_id_and_key(self, def_id); - encode_family(self, Family::Enum); - encode_item_variances(self, item.id); + self.encode_item_variances(def_id); self.encode_bounds_and_type_for_item(def_id); - encode_name(self, item.name); - encode_attributes(self, &item.attrs); - self.encode_repr_attrs(&item.attrs); self.start_tag(item_tag::children); self.seq(&enum_definition.variants, |_, v| { - tcx.map.local_def_id(v.node.data.id()) + tcx.map.local_def_id(v.node.data.id()).index }); - <[def::Export]>::encode(&[], self).unwrap(); self.end_tag(); // Encode inherent implementations for self enumeration. encode_inherent_implementations(self, def_id); - self.encode_visibility(vis); - encode_stability(self, stab); - encode_deprecation(self, depr); + (Family::Enum, EntryData::Other, EntryTypedData::Other) } hir::ItemStruct(ref struct_def, _) => { - /* Index the class*/ let def = tcx.lookup_adt_def(def_id); let variant = def.struct_variant(); - /* Now, make an item for the class itself */ - encode_def_id_and_key(self, def_id); - encode_family(self, Family::Struct(variant.kind)); self.encode_bounds_and_type_for_item(def_id); - encode_item_variances(self, item.id); - encode_name(self, item.name); - encode_attributes(self, &item.attrs); - encode_stability(self, stab); - encode_deprecation(self, depr); - self.encode_visibility(vis); - self.encode_repr_attrs(&item.attrs); + self.encode_item_variances(def_id); /* Encode def_ids for each field and method for methods, write all the stuff get_trait_method needs to know*/ - self.encode_variant_fields(variant); + let struct_ctor = if !struct_def.is_struct() { + Some(tcx.map.local_def_id(struct_def.id()).index) + } else { + None + }; + let data = self.encode_variant(variant, struct_ctor); // Encode inherent implementations for self structure. encode_inherent_implementations(self, def_id); - if !struct_def.is_struct() { - let ctor_did = tcx.map.local_def_id(struct_def.id()); - self.start_tag(item_tag::struct_ctor); - ctor_did.encode(self).unwrap(); - self.end_tag(); - } + (Family::Struct, data, EntryTypedData::Other) } hir::ItemUnion(..) => { - let def = self.tcx.lookup_adt_def(def_id); - let variant = def.struct_variant(); - - encode_def_id_and_key(self, def_id); - encode_family(self, Family::Union); self.encode_bounds_and_type_for_item(def_id); - encode_item_variances(self, item.id); - encode_name(self, item.name); - encode_attributes(self, &item.attrs); - encode_stability(self, stab); - encode_deprecation(self, depr); - self.encode_visibility(vis); - self.encode_repr_attrs(&item.attrs); + self.encode_item_variances(def_id); /* Encode def_ids for each field and method for methods, write all the stuff get_trait_method needs to know*/ - self.encode_variant_fields(variant); - - encode_inlined_item(self, InlinedItemRef::Item(def_id, item)); - self.encode_mir(def_id); + let def = self.tcx.lookup_adt_def(def_id); + let data = self.encode_variant(def.struct_variant(), None); // Encode inherent implementations for self union. encode_inherent_implementations(self, def_id); + + (Family::Union, data, EntryTypedData::Other) } hir::ItemDefaultImpl(..) => { - encode_def_id_and_key(self, def_id); - encode_family(self, Family::DefaultImpl); - encode_name(self, item.name); - - let trait_ref = tcx.impl_trait_ref(tcx.map.local_def_id(item.id)).unwrap(); - encode_trait_ref(self, trait_ref, item_tag::trait_ref); + (Family::DefaultImpl, EntryData::Other, + EntryTypedData::Impl(ImplTypedData { + trait_ref: tcx.impl_trait_ref(def_id) + })) } hir::ItemImpl(_, polarity, ..) => { - encode_def_id_and_key(self, def_id); - encode_family(self, Family::Impl); self.encode_bounds_and_type_for_item(def_id); - encode_name(self, item.name); - encode_attributes(self, &item.attrs); - - self.start_tag(item_tag::polarity); - polarity.encode(self).unwrap(); - self.end_tag(); - match - tcx.custom_coerce_unsized_kinds - .borrow() - .get(&tcx.map.local_def_id(item.id)) - { - Some(&kind) => { - self.start_tag(item_tag::impl_coerce_unsized_kind); - kind.encode(self); - self.end_tag(); - } - None => {} - } + let trait_ref = tcx.impl_trait_ref(def_id); + let parent = if let Some(trait_ref) = trait_ref { + let trait_def = tcx.lookup_trait_def(trait_ref.def_id); + trait_def.ancestors(def_id).skip(1).next().and_then(|node| { + match node { + specialization_graph::Node::Impl(parent) => Some(parent), + _ => None, + } + }) + } else { + None + }; self.start_tag(item_tag::children); - tcx.impl_or_trait_items(def_id).encode(self).unwrap(); - <[def::Export]>::encode(&[], self).unwrap(); + self.seq(&tcx.impl_or_trait_items(def_id)[..], |_, &def_id| { + assert!(def_id.is_local()); + def_id.index + }); self.end_tag(); - let did = tcx.map.local_def_id(item.id); - if let Some(trait_ref) = tcx.impl_trait_ref(did) { - encode_trait_ref(self, trait_ref, item_tag::trait_ref); - - let trait_def = tcx.lookup_trait_def(trait_ref.def_id); - let parent = trait_def.ancestors(did) - .skip(1) - .next() - .and_then(|node| match node { - specialization_graph::Node::Impl(parent) => - Some(parent), - _ => None, - }); - parent.map(|parent| { - self.start_tag(item_tag::parent_impl); - parent.encode(self).unwrap(); - self.end_tag(); - }); - } - encode_stability(self, stab); - encode_deprecation(self, depr); + (Family::Impl, + EntryData::Impl(ImplData { + polarity: polarity, + parent_impl: parent, + coerce_unsized_kind: tcx.custom_coerce_unsized_kinds.borrow() + .get(&def_id).cloned() + }), + EntryTypedData::Impl(ImplTypedData { + trait_ref: trait_ref + })) } hir::ItemTrait(..) => { - encode_def_id_and_key(self, def_id); - encode_family(self, Family::Trait); - encode_item_variances(self, item.id); + self.encode_item_variances(def_id); let trait_def = tcx.lookup_trait_def(def_id); let trait_predicates = tcx.lookup_predicates(def_id); - self.start_tag(item_tag::unsafety); - trait_def.unsafety.encode(self).unwrap(); - self.end_tag(); - - self.start_tag(item_tag::paren_sugar); - trait_def.paren_sugar.encode(self).unwrap(); - self.end_tag(); - - self.start_tag(item_tag::defaulted_trait); - tcx.trait_has_default_impl(def_id).encode(self).unwrap(); - self.end_tag(); - self.encode_generics(&trait_def.generics, &trait_predicates); self.encode_predicates(&tcx.lookup_super_predicates(def_id), item_tag::super_predicates); - encode_trait_ref(self, trait_def.trait_ref, item_tag::trait_ref); - encode_name(self, item.name); - encode_attributes(self, &item.attrs); - self.encode_visibility(vis); - encode_stability(self, stab); - encode_deprecation(self, depr); self.start_tag(item_tag::children); - tcx.impl_or_trait_items(def_id).encode(self).unwrap(); - <[def::Export]>::encode(&[], self).unwrap(); + self.seq(&tcx.impl_or_trait_items(def_id)[..], |_, &def_id| { + assert!(def_id.is_local()); + def_id.index + }); self.end_tag(); // Encode inherent implementations for self trait. encode_inherent_implementations(self, def_id); + + (Family::Trait, + EntryData::Trait(TraitData { + unsafety: trait_def.unsafety, + paren_sugar: trait_def.paren_sugar, + has_default_impl: tcx.trait_has_default_impl(def_id) + }), + EntryTypedData::Trait(TraitTypedData { + trait_ref: trait_def.trait_ref + })) } hir::ItemExternCrate(_) | hir::ItemUse(_) => { bug!("cannot encode info for item {:?}", item) } - } + }; + + self.encode_family(family); + self.encode_def_key(def_id); + self.encode_visibility(&item.vis); + encode_attributes(self, &item.attrs); + encode_stability(self, def_id); + + self.start_tag(item_tag::data); + data.encode(self).unwrap(); + self.end_tag(); + + self.start_tag(item_tag::typed_data); + typed_data.encode(self).unwrap(); + self.end_tag(); } } @@ -1084,88 +827,52 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { // no sub-item recording needed in these cases } hir::ItemEnum(..) => { - self.encode_enum_variant_infos(def_id); + self.encode_fields(def_id); + + let def = self.tcx.lookup_adt_def(def_id); + for (i, variant) in def.variants.iter().enumerate() { + self.record(variant.did, + EncodeContext::encode_enum_variant_info, + (def_id, Untracked(i))); + } } hir::ItemStruct(ref struct_def, _) => { - self.encode_addl_struct_info(def_id, struct_def.id(), item); + self.encode_fields(def_id); + + // If this is a tuple-like struct, encode the type of the constructor. + match self.tcx.lookup_adt_def(def_id).struct_variant().kind { + ty::VariantKind::Struct => { + // no value for structs like struct Foo { ... } + } + ty::VariantKind::Tuple | ty::VariantKind::Unit => { + // there is a value for structs like `struct + // Foo()` and `struct Foo` + let ctor_def_id = self.tcx.map.local_def_id(struct_def.id()); + self.record(ctor_def_id, + EncodeContext::encode_struct_ctor, + ctor_def_id); + } + } } hir::ItemUnion(..) => { - self.encode_addl_union_info(def_id); - } - hir::ItemImpl(.., ref ast_items) => { - self.encode_addl_impl_info(def_id, item.id, ast_items); + self.encode_fields(def_id); } - hir::ItemTrait(.., ref trait_items) => { - self.encode_addl_trait_info(def_id, trait_items); - } - } - } - - fn encode_addl_struct_info(&mut self, - def_id: DefId, - struct_node_id: ast::NodeId, - item: &hir::Item) { - let def = self.tcx.lookup_adt_def(def_id); - let variant = def.struct_variant(); - - self.encode_fields(def_id); - - // If this is a tuple-like struct, encode the type of the constructor. - match variant.kind { - ty::VariantKind::Struct => { - // no value for structs like struct Foo { ... } + hir::ItemImpl(..) => { + for &trait_item_def_id in &self.tcx.impl_or_trait_items(def_id)[..] { + self.record(trait_item_def_id, + EncodeContext::encode_info_for_impl_item, + trait_item_def_id); + } } - ty::VariantKind::Tuple | ty::VariantKind::Unit => { - // there is a value for structs like `struct - // Foo()` and `struct Foo` - let ctor_def_id = self.tcx.map.local_def_id(struct_node_id); - self.record(ctor_def_id, - EncodeContext::encode_struct_ctor, - (def_id, item.id, struct_node_id)); + hir::ItemTrait(..) => { + for &item_def_id in &self.tcx.impl_or_trait_items(def_id)[..] { + self.record(item_def_id, + EncodeContext::encode_info_for_trait_item, + item_def_id); + } } } } - - fn encode_addl_union_info(&mut self, def_id: DefId) { - self.encode_fields(def_id); - } - - fn encode_addl_impl_info(&mut self, - def_id: DefId, - impl_id: ast::NodeId, - ast_items: &[hir::ImplItem]) { - let items = self.tcx.impl_or_trait_items(def_id); - - // Iterate down the trait items, emitting them. We rely on the - // assumption that all of the actually implemented trait items - // appear first in the impl structure, in the same order they do - // in the ast. This is a little sketchy. - let num_implemented_methods = ast_items.len(); - for (i, &trait_item_def_id) in items.iter().enumerate() { - let ast_item = if i < num_implemented_methods { - Some(&ast_items[i]) - } else { - None - }; - - self.record(trait_item_def_id, - EncodeContext::encode_info_for_impl_item, - (impl_id, trait_item_def_id, ast_item)); - } - } - - fn encode_addl_trait_info(&mut self, - def_id: DefId, - trait_items: &[hir::TraitItem]) { - // Now output the trait item info for each trait item. - let r = self.tcx.impl_or_trait_items(def_id); - for (&item_def_id, trait_item) in r.iter().zip(trait_items) { - assert!(item_def_id.is_local()); - self.record(item_def_id, - EncodeContext::encode_info_for_trait_item, - (def_id, item_def_id, trait_item)); - } - } } impl<'a, 'tcx> EncodeContext<'a, 'tcx> { @@ -1175,37 +882,30 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { debug!("writing foreign item {}", tcx.node_path_str(nitem.id)); - encode_def_id_and_key(self, def_id); - let parent_id = tcx.map.get_parent(nitem.id); - self.encode_parent_item(tcx.map.local_def_id(parent_id)); + self.encode_def_key(def_id); self.encode_visibility(&nitem.vis); - match nitem.node { + self.encode_bounds_and_type_for_item(def_id); + let family = match nitem.node { hir::ForeignItemFn(ref fndecl, _) => { - encode_family(self, Family::Fn); - self.encode_bounds_and_type_for_item(def_id); - encode_name(self, nitem.name); - encode_attributes(self, &nitem.attrs); - let stab = tcx.lookup_stability(tcx.map.local_def_id(nitem.id)); - let depr = tcx.lookup_deprecation(tcx.map.local_def_id(nitem.id)); - encode_stability(self, stab); - encode_deprecation(self, depr); - self.encode_method_argument_names(&fndecl); - } - hir::ForeignItemStatic(_, mutbl) => { - encode_family(self, if mutbl { - Family::MutStatic - } else { - Family::ImmStatic - }); - self.encode_bounds_and_type_for_item(def_id); - encode_attributes(self, &nitem.attrs); - let stab = tcx.lookup_stability(tcx.map.local_def_id(nitem.id)); - let depr = tcx.lookup_deprecation(tcx.map.local_def_id(nitem.id)); - encode_stability(self, stab); - encode_deprecation(self, depr); - encode_name(self, nitem.name); + self.encode_fn_arg_names(&fndecl); + + Family::ForeignFn } - } + hir::ForeignItemStatic(_, true) => Family::ForeignMutStatic, + hir::ForeignItemStatic(_, false) => Family::ForeignImmStatic + }; + self.encode_family(family); + + self.start_tag(item_tag::data); + EntryData::Other.encode(self).unwrap(); + self.end_tag(); + + self.start_tag(item_tag::typed_data); + EntryTypedData::Other.encode(self).unwrap(); + self.end_tag(); + + encode_attributes(self, &nitem.attrs); + encode_stability(self, def_id); } } @@ -1267,21 +967,25 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn encode_info_for_anon_ty(&mut self, def_id: DefId) { - encode_def_id_and_key(self, def_id); + self.encode_def_key(def_id); self.encode_bounds_and_type_for_item(def_id); } fn encode_info_for_closure(&mut self, def_id: DefId) { let tcx = self.tcx; - encode_def_id_and_key(self, def_id); - encode_name(self, syntax::parse::token::intern("")); + self.encode_def_key(def_id); + self.encode_family(Family::Closure); - self.start_tag(item_tag::closure_ty); - tcx.tables.borrow().closure_tys[&def_id].encode(self).unwrap(); + self.start_tag(item_tag::data); + EntryData::Closure(ClosureData { + kind: tcx.closure_kind(def_id) + }).encode(self).unwrap(); self.end_tag(); - self.start_tag(item_tag::closure_kind); - tcx.closure_kind(def_id).encode(self).unwrap(); + self.start_tag(item_tag::typed_data); + EntryTypedData::Closure(ClosureTypedData { + ty: tcx.tables.borrow().closure_tys[&def_id].clone() + }).encode(self).unwrap(); self.end_tag(); assert!(self.mir_map.map.contains_key(&def_id)); @@ -1292,16 +996,14 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn encode_info_for_items(ecx: &mut EncodeContext) -> IndexData { let krate = ecx.tcx.map.krate(); - ecx.start_tag(root_tag::items); + // FIXME(eddyb) Avoid wrapping the items in a doc. + ecx.start_tag(0).unwrap(); let items = { let mut index = IndexBuilder::new(ecx); index.record(DefId::local(CRATE_DEF_INDEX), EncodeContext::encode_info_for_mod, - FromId(CRATE_NODE_ID, (&krate.module, - &krate.attrs, - syntax::parse::token::intern(&ecx.link_meta.crate_name), - &hir::Public))); + FromId(CRATE_NODE_ID, (&krate.module, &krate.attrs, &hir::Public))); let mut visitor = EncodeVisitor { index: index, }; @@ -1354,8 +1056,7 @@ fn encode_crate_deps(ecx: &mut EncodeContext, cstore: &cstore::CStore) { // but is enough to get transitive crate dependencies working. ecx.start_tag(root_tag::crate_deps); ecx.seq(&get_ordered_deps(cstore), |_, &(_, ref dep)| { - (dep.name(), decoder::get_crate_hash(dep.data()), - dep.explicitly_linked.get()) + (dep.name(), dep.hash(), dep.explicitly_linked.get()) }); ecx.end_tag(); } @@ -1406,18 +1107,6 @@ fn encode_native_libraries(ecx: &mut EncodeContext) { ecx.end_tag(); } -fn encode_plugin_registrar_fn(ecx: &mut EncodeContext) { - match ecx.tcx.sess.plugin_registrar_fn.get() { - Some(id) => { - let def_id = ecx.tcx.map.local_def_id(id); - ecx.start_tag(root_tag::plugin_registrar_fn); - def_id.index.encode(ecx).unwrap(); - ecx.end_tag(); - } - None => {} - } -} - fn encode_codemap(ecx: &mut EncodeContext) { let codemap = ecx.tcx.sess.codemap(); let all_filemaps = codemap.files.borrow(); @@ -1448,15 +1137,6 @@ fn encode_macro_defs(ecx: &mut EncodeContext) { (def.name, &def.attrs, def.span, body) }); ecx.end_tag(); - - if ecx.tcx.sess.crate_types.borrow().contains(&CrateTypeRustcMacro) { - let id = ecx.tcx.sess.derive_registrar_fn.get().unwrap(); - let did = ecx.tcx.map.local_def_id(id); - - ecx.start_tag(root_tag::macro_derive_registrar); - did.index.encode(ecx).unwrap(); - ecx.end_tag(); - } } struct ImplVisitor<'a, 'tcx:'a> { @@ -1601,30 +1281,29 @@ fn encode_metadata_inner(ecx: &mut EncodeContext) { let tcx = ecx.tcx; let link_meta = ecx.link_meta; - ecx.start_tag(root_tag::crate_crate_name); - link_meta.crate_name.encode(ecx).unwrap(); - ecx.end_tag(); - - ecx.start_tag(root_tag::crate_triple); - tcx.sess.opts.target_triple.encode(ecx).unwrap(); - ecx.end_tag(); - - ecx.start_tag(root_tag::crate_hash); - link_meta.crate_hash.encode(ecx).unwrap(); - ecx.end_tag(); - - ecx.start_tag(root_tag::crate_disambiguator); - tcx.sess.local_crate_disambiguator().encode(ecx).unwrap(); - ecx.end_tag(); - - encode_dylib_dependency_formats(ecx); - - ecx.start_tag(root_tag::panic_strategy); - ecx.tcx.sess.opts.cg.panic.encode(ecx); + ecx.start_tag(root_tag::crate_info); + let is_rustc_macro = tcx.sess.crate_types.borrow().contains(&CrateTypeRustcMacro); + CrateInfo { + name: link_meta.crate_name.clone(), + triple: tcx.sess.opts.target_triple.clone(), + hash: link_meta.crate_hash, + disambiguator: tcx.sess.local_crate_disambiguator().to_string(), + panic_strategy: tcx.sess.opts.cg.panic.clone(), + plugin_registrar_fn: tcx.sess.plugin_registrar_fn.get().map(|id| { + tcx.map.local_def_id(id).index + }), + macro_derive_registrar: if is_rustc_macro { + let id = tcx.sess.derive_registrar_fn.get().unwrap(); + Some(tcx.map.local_def_id(id).index) + } else { + None + } + }.encode(ecx).unwrap(); ecx.end_tag(); let mut i = ecx.position(); encode_crate_deps(ecx, ecx.cstore); + encode_dylib_dependency_formats(ecx); let dep_bytes = ecx.position() - i; // Encode the language items. @@ -1637,11 +1316,6 @@ fn encode_metadata_inner(ecx: &mut EncodeContext) { encode_native_libraries(ecx); let native_lib_bytes = ecx.position() - i; - // Encode the plugin registrar function - i = ecx.position(); - encode_plugin_registrar_fn(ecx); - let plugin_registrar_fn_bytes = ecx.position() - i; - // Encode codemap i = ecx.position(); encode_codemap(ecx); @@ -1689,7 +1363,6 @@ fn encode_metadata_inner(ecx: &mut EncodeContext) { println!(" dep bytes: {}", dep_bytes); println!(" lang item bytes: {}", lang_item_bytes); println!(" native bytes: {}", native_lib_bytes); - println!("plugin registrar bytes: {}", plugin_registrar_fn_bytes); println!(" codemap bytes: {}", codemap_bytes); println!(" macro def bytes: {}", macro_defs_bytes); println!(" impl bytes: {}", impl_bytes); diff --git a/src/librustc_metadata/index.rs b/src/librustc_metadata/index.rs index 63d7f1b58bb0d..98a43c7639c33 100644 --- a/src/librustc_metadata/index.rs +++ b/src/librustc_metadata/index.rs @@ -53,6 +53,18 @@ impl Index { Some(position) } } + + pub fn iter_enumerated<'a>(&self, bytes: &'a [u8]) + -> impl Iterator + 'a { + let words = bytes_to_words(&bytes[self.data_start..self.data_end]); + words.iter().enumerate().filter_map(|(index, &position)| { + if position == u32::MAX { + None + } else { + Some((DefIndex::new(index), u32::from_be(position))) + } + }) + } } /// While we are generating the metadata, we also track the position diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs index b7125daa4ad57..b46c5be9f8a87 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -51,26 +51,24 @@ extern crate rustc_const_math; #[cfg(test)] extern crate test; -pub mod rbml { +mod rbml { pub mod writer; pub mod reader; pub use self::reader::Doc; } -pub use rustc::middle; +mod diagnostics; -pub mod diagnostics; - -pub mod astencode; -pub mod common; -pub mod def_key; -pub mod encoder; +mod astencode; +mod common; mod index_builder; -pub mod decoder; +mod index; +mod encoder; +mod decoder; +mod csearch; + pub mod creader; -pub mod csearch; pub mod cstore; -pub mod index; pub mod loader; pub mod macro_import; diff --git a/src/librustc_metadata/loader.rs b/src/librustc_metadata/loader.rs index a4f8ee4779905..47bf65bead9af 100644 --- a/src/librustc_metadata/loader.rs +++ b/src/librustc_metadata/loader.rs @@ -511,9 +511,8 @@ impl<'a> Context<'a> { if let Some((ref p, _)) = lib.rlib { err.note(&format!("path: {}", p.display())); } - let data = lib.metadata.as_slice(); - let name = decoder::get_crate_name(data); - note_crate_name(&mut err, &name); + let crate_info = decoder::get_crate_info(lib.metadata.as_slice()); + note_crate_name(&mut err, &crate_info.name); } err.emit(); None @@ -610,33 +609,27 @@ impl<'a> Context<'a> { return None; } + let crate_info = decoder::get_crate_info(crate_data); if self.should_match_name { - match decoder::maybe_get_crate_name(crate_data) { - Some(ref name) if self.crate_name == *name => {} - _ => { info!("Rejecting via crate name"); return None } + if self.crate_name != crate_info.name { + info!("Rejecting via crate name"); return None; } } - let hash = match decoder::maybe_get_crate_hash(crate_data) { - None => { info!("Rejecting via lack of crate hash"); return None; } - Some(h) => h, - }; - let triple = match decoder::get_crate_triple(crate_data) { - None => { debug!("triple not present"); return None } - Some(t) => t, - }; - if triple != self.triple { - info!("Rejecting via crate triple: expected {} got {}", self.triple, triple); + if crate_info.triple != self.triple { + info!("Rejecting via crate triple: expected {} got {}", + self.triple, crate_info.triple); self.rejected_via_triple.push(CrateMismatch { path: libpath.to_path_buf(), - got: triple.to_string() + got: crate_info.triple }); return None; } if let Some(myhash) = self.hash { - if *myhash != hash { - info!("Rejecting via hash: expected {} got {}", *myhash, hash); + if *myhash != crate_info.hash { + info!("Rejecting via hash: expected {} got {}", + *myhash, crate_info.hash); self.rejected_via_hash.push(CrateMismatch { path: libpath.to_path_buf(), got: myhash.to_string() @@ -645,7 +638,7 @@ impl<'a> Context<'a> { } } - Some(hash) + Some(crate_info.hash) } diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 248690befac0e..6283ff2187ab8 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -271,7 +271,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, // Tuple-like ADTs are represented as ExprCall. We convert them here. expr_ty.ty_adt_def().and_then(|adt_def|{ match cx.tcx.expect_def(fun.id) { - Def::Variant(_, variant_id) => { + Def::Variant(variant_id) => { Some((adt_def, adt_def.variant_index_with_id(variant_id))) }, Def::Struct(..) => { @@ -480,8 +480,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } AdtKind::Enum => { match cx.tcx.expect_def(expr.id) { - Def::Variant(enum_id, variant_id) => { - debug_assert!(adt.did == enum_id); + Def::Variant(variant_id) => { assert!(base.is_none()); let index = adt.variant_index_with_id(variant_id); @@ -688,13 +687,12 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, }, ref sty => bug!("unexpected sty: {:?}", sty) }, - Def::Variant(enum_id, variant_id) => match cx.tcx.node_id_to_type(expr.id).sty { + Def::Variant(variant_id) => match cx.tcx.node_id_to_type(expr.id).sty { // A variant constructor. Should only be reached if not called in the same // expression. ty::TyFnDef(..) => variant_id, // A unit variant, similar special case to the struct case above. ty::TyAdt(adt_def, substs) => { - debug_assert!(adt_def.did == enum_id); let index = adt_def.variant_index_with_id(variant_id); return ExprKind::Adt { adt_def: adt_def, diff --git a/src/librustc_mir/hair/cx/pattern.rs b/src/librustc_mir/hair/cx/pattern.rs index 2c946b078a2f5..7b8446b184fb3 100644 --- a/src/librustc_mir/hair/cx/pattern.rs +++ b/src/librustc_mir/hair/cx/pattern.rs @@ -301,7 +301,8 @@ impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> { subpatterns: Vec>) -> PatternKind<'tcx> { match self.cx.tcx.expect_def(pat.id) { - Def::Variant(enum_id, variant_id) => { + Def::Variant(variant_id) => { + let enum_id = self.cx.tcx.parent_def_id(variant_id).unwrap(); let adt_def = self.cx.tcx.lookup_adt_def(enum_id); if adt_def.variants.len() > 1 { PatternKind::Variant { diff --git a/src/librustc_passes/static_recursion.rs b/src/librustc_passes/static_recursion.rs index d23f77af32155..0ab8e2d7fcd28 100644 --- a/src/librustc_passes/static_recursion.rs +++ b/src/librustc_passes/static_recursion.rs @@ -272,15 +272,13 @@ impl<'a, 'ast: 'a> Visitor<'ast> for CheckItemRecursionVisitor<'a, 'ast> { // affect the specific variant used, but we need to check // the whole enum definition to see what expression that // might be (if any). - Some(Def::Variant(enum_id, variant_id)) => { - if let Some(enum_node_id) = self.ast_map.as_local_node_id(enum_id) { - if let hir::ItemEnum(ref enum_def, ref generics) = self.ast_map - .expect_item(enum_node_id) - .node { + Some(Def::Variant(variant_id)) => { + if let Some(variant_id) = self.ast_map.as_local_node_id(variant_id) { + let variant = self.ast_map.expect_variant(variant_id); + let enum_id = self.ast_map.get_parent(variant_id); + let enum_item = self.ast_map.expect_item(enum_id); + if let hir::ItemEnum(ref enum_def, ref generics) = enum_item.node { self.populate_enum_discriminants(enum_def); - let enum_id = self.ast_map.as_local_node_id(enum_id).unwrap(); - let variant_id = self.ast_map.as_local_node_id(variant_id).unwrap(); - let variant = self.ast_map.expect_variant(variant_id); self.visit_variant(variant, generics, enum_id); } else { span_bug!(e.span, diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 4012c1cb34889..1b119fd008509 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -323,8 +323,13 @@ impl<'b, 'a, 'tcx: 'a, 'v> Visitor<'v> for ReachEverythingInTheInterfaceVisitor< let def = self.ev.tcx.expect_def(ty.id); match def { Def::Struct(def_id) | Def::Union(def_id) | Def::Enum(def_id) | - Def::TyAlias(def_id) | Def::Trait(def_id) | Def::AssociatedTy(def_id, _) => { - if let Some(node_id) = self.ev.tcx.map.as_local_node_id(def_id) { + Def::TyAlias(def_id) | Def::Trait(def_id) | Def::AssociatedTy(def_id) => { + if let Some(mut node_id) = self.ev.tcx.map.as_local_node_id(def_id) { + // Check the trait for associated types. + if let hir::map::NodeTraitItem(_) = self.ev.tcx.map.get(node_id) { + node_id = self.ev.tcx.map.get_parent(node_id); + } + let item = self.ev.tcx.map.expect_item(node_id); if let Def::TyAlias(..) = def { // Type aliases are substituted. Associated type aliases are not @@ -947,9 +952,14 @@ impl<'a, 'tcx: 'a, 'v> Visitor<'v> for SearchInterfaceForPrivateItemsVisitor<'a, return } Def::Struct(def_id) | Def::Union(def_id) | Def::Enum(def_id) | - Def::TyAlias(def_id) | Def::Trait(def_id) | Def::AssociatedTy(def_id, _) => { + Def::TyAlias(def_id) | Def::Trait(def_id) | Def::AssociatedTy(def_id) => { // Non-local means public (private items can't leave their crate, modulo bugs) - if let Some(node_id) = self.tcx.map.as_local_node_id(def_id) { + if let Some(mut node_id) = self.tcx.map.as_local_node_id(def_id) { + // Check the trait for associated types. + if let hir::map::NodeTraitItem(_) = self.tcx.map.get(node_id) { + node_id = self.tcx.map.get_parent(node_id); + } + let item = self.tcx.map.expect_item(node_id); let vis = match self.substituted_alias_visibility(item, path) { Some(vis) => vis, diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 7264dcea9553e..77a01aac73956 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -24,6 +24,7 @@ use {resolve_error, resolve_struct_error, ResolutionError}; use rustc::middle::cstore::ChildItem; use rustc::hir::def::*; use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId}; +use rustc::hir::map::DefPathData; use rustc::ty; use std::cell::Cell; @@ -250,8 +251,7 @@ impl<'b> Resolver<'b> { self.define(parent, name, TypeNS, (module, sp, vis)); for variant in &(*enum_definition).variants { - let item_def_id = self.definitions.local_def_id(item.id); - self.build_reduced_graph_for_variant(variant, item_def_id, module, vis); + self.build_reduced_graph_for_variant(variant, module, vis); } } @@ -314,7 +314,7 @@ impl<'b> Resolver<'b> { is_static_method = !sig.decl.has_self(); (Def::Method(item_def_id), ValueNS) } - TraitItemKind::Type(..) => (Def::AssociatedTy(def_id, item_def_id), TypeNS), + TraitItemKind::Type(..) => (Def::AssociatedTy(item_def_id), TypeNS), TraitItemKind::Macro(_) => panic!("unexpanded macro in resolve!"), }; @@ -334,7 +334,6 @@ impl<'b> Resolver<'b> { // type and value namespaces. fn build_reduced_graph_for_variant(&mut self, variant: &Variant, - item_id: DefId, parent: Module<'b>, vis: ty::Visibility) { let name = variant.node.name.name; @@ -346,7 +345,7 @@ impl<'b> Resolver<'b> { // Variants are always treated as importable to allow them to be glob used. // All variants are defined in both type and value namespaces as future-proofing. - let def = Def::Variant(item_id, self.definitions.local_def_id(variant.node.data.id())); + let def = Def::Variant(self.definitions.local_def_id(variant.node.data.id())); self.define(parent, name, ValueNS, (def, variant.span, vis)); self.define(parent, name, TypeNS, (def, variant.span, vis)); } @@ -389,20 +388,12 @@ impl<'b> Resolver<'b> { /// Builds the reduced graph for a single item in an external crate. fn build_reduced_graph_for_external_crate_def(&mut self, parent: Module<'b>, child: ChildItem) { - if let Def::ForeignMod(def_id) = child.def { - // Foreign modules have no names. Recur and populate eagerly. - for child in self.session.cstore.item_children(def_id) { - self.build_reduced_graph_for_external_crate_def(parent, child); - } - return; - } - let def = child.def; let name = child.name; let vis = if parent.is_trait() { ty::Visibility::Public } else { child.vis }; match def { - Def::Mod(_) | Def::ForeignMod(_) | Def::Enum(..) => { + Def::Mod(_) | Def::Enum(..) => { debug!("(building reduced graph for external crate) building module {} {:?}", name, vis); let parent_link = ModuleParentLink(parent, name); @@ -434,7 +425,8 @@ impl<'b> Resolver<'b> { let trait_item_def_ids = self.session.cstore.impl_or_trait_items(def_id); for &trait_item_def in &trait_item_def_ids { let trait_item_name = - self.session.cstore.item_name(trait_item_def); + self.session.cstore.opt_item_name(trait_item_def) + .expect("opt_item_name returned None for trait"); debug!("(building reduced graph for external crate) ... adding trait item \ '{}'", @@ -452,7 +444,9 @@ impl<'b> Resolver<'b> { let _ = self.try_define(parent, name, TypeNS, (def, DUMMY_SP, vis)); } Def::Struct(def_id) - if self.session.cstore.tuple_struct_definition_if_ctor(def_id).is_none() => { + if self.session.cstore.def_key(def_id).disambiguated_data.data != + DefPathData::StructCtor + => { debug!("(building reduced graph for external crate) building type and value for {}", name); let _ = self.try_define(parent, name, TypeNS, (def, DUMMY_SP, vis)); diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index b03e76c829a3e..016b621eabd4c 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -2757,7 +2757,7 @@ impl<'a> Resolver<'a> { if let Some(resolution) = self.def_map.get(&node_id) { match resolution.base_def { Def::Enum(did) | Def::TyAlias(did) | Def::Union(did) | - Def::Struct(did) | Def::Variant(_, did) if resolution.depth == 0 => { + Def::Struct(did) | Def::Variant(did) if resolution.depth == 0 => { if let Some(fields) = self.structs.get(&did) { if fields.iter().any(|&field_name| name == field_name) { return Field; @@ -2826,7 +2826,7 @@ impl<'a> Resolver<'a> { if let Some(path_res) = self.resolve_possibly_assoc_item(expr.id, maybe_qself.as_ref(), path, ValueNS) { // Check if struct variant - let is_struct_variant = if let Def::Variant(_, variant_id) = path_res.base_def { + let is_struct_variant = if let Def::Variant(variant_id) = path_res.base_def { self.structs.contains_key(&variant_id) } else { false diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 2cbc110c56af9..79fcff7d8a166 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -293,8 +293,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { let def = self.tcx.expect_def(ref_id); match def { - Def::Mod(_) | - Def::ForeignMod(_) => { + Def::Mod(_) => { self.dumper.mod_ref(ModRefData { span: sub_span.expect("No span found for mod ref"), ref_id: Some(def_id), diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 00c9ea3af182e..cbdce3229c7c7 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1373,7 +1373,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { item.expect("missing associated type").def_id() }; - (ty, Def::AssociatedTy(trait_did, item_did)) + (ty, Def::AssociatedTy(item_did)) } fn qpath_to_ty(&self, @@ -1522,8 +1522,9 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { tcx.prohibit_type_params(base_segments); tcx.mk_self_type() } - Def::AssociatedTy(trait_did, _) => { + Def::AssociatedTy(def_id) => { tcx.prohibit_type_params(&base_segments[..base_segments.len()-2]); + let trait_did = tcx.parent_def_id(def_id).unwrap(); self.qpath_to_ty(rscope, span, param_mode, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 3a854da1d4802..e38b865842e8a 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3224,7 +3224,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.set_tainted_by_errors(); return None; } - Def::Variant(type_did, _) | Def::Struct(type_did) | Def::Union(type_did) => { + Def::Variant(did) => { + let type_did = self.tcx.parent_def_id(did).unwrap(); + Some((type_did, self.tcx.expect_variant_def(def))) + } + Def::Struct(type_did) | Def::Union(type_did) => { Some((type_did, self.tcx.expect_variant_def(def))) } Def::TyAlias(did) => { @@ -4115,10 +4119,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Case 1 and 1b. Reference to a *type* or *enum variant*. Def::Struct(def_id) | Def::Union(def_id) | - Def::Variant(_, def_id) | + Def::Variant(def_id) | Def::Enum(def_id) | Def::TyAlias(def_id) | - Def::AssociatedTy(_, def_id) | + Def::AssociatedTy(def_id) | Def::Trait(def_id) => { // Everything but the final segment should have no // parameters at all. @@ -4166,7 +4170,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // here. If they do, an error will have been reported // elsewhere. (I hope) Def::Mod(..) | - Def::ForeignMod(..) | Def::PrimTy(..) | Def::SelfTy(..) | Def::TyParam(..) | diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index e72ea60072e08..855b135b8636a 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -17,6 +17,7 @@ use rustc::hir; use rustc::hir::def::Def; use rustc::hir::def_id::DefId; +use rustc::hir::map::DefPathData; use rustc::hir::print as pprust; use rustc::ty::{self, TyCtxt, VariantKind}; use rustc::util::nodemap::FnvHashSet; @@ -82,7 +83,7 @@ fn try_inline_def<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>, } Def::Struct(did) // If this is a struct constructor, we skip it - if tcx.sess.cstore.tuple_struct_definition_if_ctor(did).is_none() => { + if tcx.def_key(did).disambiguated_data.data != DefPathData::StructCtor => { record_extern_fqn(cx, did, clean::TypeStruct); ret.extend(build_impls(cx, tcx, did)); clean::StructItem(build_struct(cx, tcx, did)) @@ -497,17 +498,10 @@ fn build_module<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>, // visit each node at most once. let mut visited = FnvHashSet(); for item in tcx.sess.cstore.item_children(did) { - match item.def { - Def::ForeignMod(did) => { - fill_in(cx, tcx, did, items); - } - def => { - if item.vis == ty::Visibility::Public { - if !visited.insert(def) { continue } - if let Some(i) = try_inline_def(cx, tcx, def) { - items.extend(i) - } - } + if item.vis == ty::Visibility::Public { + if !visited.insert(item.def) { continue } + if let Some(i) = try_inline_def(cx, tcx, item.def) { + items.extend(i) } } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index f9d7eb50edaec..43a9b4e49e393 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1161,7 +1161,7 @@ impl<'a, 'tcx> Clean for (DefId, &'a ty::PolyFnSig<'tcx>) { let mut names = if cx.map.as_local_node_id(did).is_some() { vec![].into_iter() } else { - cx.tcx().sess.cstore.method_arg_names(did).into_iter() + cx.tcx().sess.cstore.fn_arg_names(did).into_iter() }.peekable(); FnDecl { output: Return(sig.0.output.clean(cx)), @@ -2757,6 +2757,8 @@ fn resolve_type(cx: &DocContext, fn register_def(cx: &DocContext, def: Def) -> DefId { debug!("register_def({:?})", def); + let tcx = cx.tcx(); + let (did, kind) = match def { Def::Fn(i) => (i, TypeFunction), Def::TyAlias(i) => (i, TypeTypedef), @@ -2766,7 +2768,7 @@ fn register_def(cx: &DocContext, def: Def) -> DefId { Def::Union(i) => (i, TypeUnion), Def::Mod(i) => (i, TypeModule), Def::Static(i, _) => (i, TypeStatic), - Def::Variant(i, _) => (i, TypeEnum), + Def::Variant(i) => (tcx.parent_def_id(i).unwrap(), TypeEnum), Def::SelfTy(Some(def_id), _) => (def_id, TypeTrait), Def::SelfTy(_, Some(impl_def_id)) => { return impl_def_id @@ -2774,10 +2776,6 @@ fn register_def(cx: &DocContext, def: Def) -> DefId { _ => return def.def_id() }; if did.is_local() { return did } - let tcx = match cx.tcx_opt() { - Some(tcx) => tcx, - None => return did - }; inline::record_extern_fqn(cx, did, kind); if let TypeTrait = kind { let t = inline::build_external_trait(cx, tcx, did); diff --git a/src/librustdoc/visit_lib.rs b/src/librustdoc/visit_lib.rs index da11f652b4b34..d93ca75a8da02 100644 --- a/src/librustdoc/visit_lib.rs +++ b/src/librustdoc/visit_lib.rs @@ -68,7 +68,6 @@ impl<'a, 'b, 'tcx> LibEmbargoVisitor<'a, 'b, 'tcx> { for item in self.cstore.item_children(did) { match item.def { Def::Mod(did) | - Def::ForeignMod(did) | Def::Trait(did) | Def::Struct(did) | Def::Union(did) | @@ -84,9 +83,10 @@ impl<'a, 'b, 'tcx> LibEmbargoVisitor<'a, 'b, 'tcx> { } fn visit_item(&mut self, did: DefId, item: ChildItem) { - let inherited_item_level = match item.def { - Def::ForeignMod(..) => self.prev_level, - _ => if item.vis == Visibility::Public { self.prev_level } else { None } + let inherited_item_level = if item.vis == Visibility::Public { + self.prev_level + } else { + None }; let item_level = self.update(did, inherited_item_level); From cc47dc5c6e2502f554c465bef5a8f883139c0c4e Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Thu, 8 Sep 2016 19:54:29 +0300 Subject: [PATCH 24/39] rustc_metadata: store dense indexes in little-endian instead of big. --- src/librustc_metadata/index.rs | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/src/librustc_metadata/index.rs b/src/librustc_metadata/index.rs index 98a43c7639c33..80d5141c99ca5 100644 --- a/src/librustc_metadata/index.rs +++ b/src/librustc_metadata/index.rs @@ -44,7 +44,7 @@ impl Index { debug!("lookup_item: index={:?} words.len={:?}", index, words.len()); - let position = u32::from_be(words[index]); + let position = u32::from_le(words[index]); if position == u32::MAX { debug!("lookup_item: position=u32::MAX"); None @@ -61,7 +61,7 @@ impl Index { if position == u32::MAX { None } else { - Some((DefIndex::new(index), u32::from_be(position))) + Some((DefIndex::new(index), u32::from_le(position))) } }) } @@ -100,13 +100,11 @@ impl IndexData { "recorded position for item {:?} twice, first at {:?} and now at {:?}", item, self.positions[item], position); - self.positions[item] = position; + self.positions[item] = position.to_le(); } pub fn write_index(&self, buf: &mut Cursor>) { - for &position in &self.positions { - write_be_u32(buf, position); - } + buf.write_all(words_to_bytes(&self.positions)).unwrap(); } } @@ -120,7 +118,7 @@ pub struct DenseIndex { impl DenseIndex { pub fn lookup(&self, buf: &[u8], ix: u32) -> Option { let data = bytes_to_words(&buf[self.start..self.end]); - data.get(ix as usize).map(|d| u32::from_be(*d)) + data.get(ix as usize).map(|d| u32::from_le(*d)) } pub fn from_buf(buf: &[u8], start: usize, end: usize) -> Self { assert!((end-start)%4 == 0 && start <= end && end <= buf.len()); @@ -135,23 +133,16 @@ pub fn write_dense_index(entries: Vec, buf: &mut Cursor>) { let elen = entries.len(); assert!(elen < u32::MAX as usize); - for entry in entries { - write_be_u32(buf, entry); - } + buf.write_all(words_to_bytes(&entries)).unwrap(); info!("write_dense_index: {} entries", elen); } -fn write_be_u32(w: &mut W, u: u32) { - let _ = w.write_all(&[ - (u >> 24) as u8, - (u >> 16) as u8, - (u >> 8) as u8, - (u >> 0) as u8, - ]); -} - fn bytes_to_words(b: &[u8]) -> &[u32] { assert!(b.len() % 4 == 0); unsafe { slice::from_raw_parts(b.as_ptr() as *const u32, b.len()/4) } } + +fn words_to_bytes(w: &[u32]) -> &[u8] { + unsafe { slice::from_raw_parts(w.as_ptr() as *const u8, w.len()*4) } +} From 6890354f3b43c98ff0e329fe7cf952eb1176ce61 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Thu, 8 Sep 2016 21:36:22 +0300 Subject: [PATCH 25/39] rustc_metadata: use the shorthand encoding for predicates also. --- src/librustc_metadata/common.rs | 6 +- src/librustc_metadata/creader.rs | 1 - src/librustc_metadata/cstore.rs | 1 - src/librustc_metadata/decoder.rs | 39 ++++++----- src/librustc_metadata/encoder.rs | 110 ++++++++++++------------------- src/librustc_metadata/index.rs | 30 --------- 6 files changed, 65 insertions(+), 122 deletions(-) diff --git a/src/librustc_metadata/common.rs b/src/librustc_metadata/common.rs index e068395f729a4..f30551cadd97a 100644 --- a/src/librustc_metadata/common.rs +++ b/src/librustc_metadata/common.rs @@ -72,8 +72,6 @@ pub mod root_tag { pub const crate_info: usize = 0x104; pub const index: usize = 0x110; - pub const xref_index: usize = 0x111; - pub const xref_data: usize = 0x112; pub const crate_deps: usize = 0x102; pub const dylib_dependency_formats: usize = 0x106; pub const native_libraries: usize = 0x10a; @@ -202,7 +200,7 @@ pub mod item_tag { pub const fn_arg_names: usize = 0x85; } -/// The shorthand encoding of `Ty` uses `TypeVariants`' variant `usize` +/// The shorthand encoding uses an enum's variant index `usize` /// and is offset by this value so it never matches a real variant. /// This offset is also chosen so that the first byte is never < 0x80. -pub const TYPE_SHORTHAND_OFFSET: usize = 0x80; +pub const SHORTHAND_OFFSET: usize = 0x80; diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index dd6ef73ccdbd7..73dcf9470183b 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -329,7 +329,6 @@ impl<'a> CrateReader<'a> { extern_crate: Cell::new(None), info: crate_info, index: decoder::load_index(metadata.as_slice()), - xref_index: decoder::load_xrefs(metadata.as_slice()), key_map: decoder::load_key_map(metadata.as_slice()), data: metadata, cnum_map: RefCell::new(cnum_map), diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index c6cbe6db9098b..44fdf29aa73c4 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -80,7 +80,6 @@ pub struct CrateMetadata { pub info: common::CrateInfo, pub index: index::Index, - pub xref_index: index::DenseIndex, /// For each public item in this crate, we encode a key. When the /// crate is loaded, we read all the keys and put them in this diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index f3283451b93b8..c665a7be955dc 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -243,10 +243,10 @@ impl<'a, 'tcx> SpecializedDecoder> for DecodeContext<'a, 'tcx> { // Handle shorthands first, if we have an usize > 0x80. if self.opaque.data[self.opaque.position()] & 0x80 != 0 { let pos = self.read_usize()?; - assert!(pos >= TYPE_SHORTHAND_OFFSET); + assert!(pos >= SHORTHAND_OFFSET); let key = ty::CReaderCacheKey { cnum: self.cdata().cnum, - pos: pos - TYPE_SHORTHAND_OFFSET + pos: pos - SHORTHAND_OFFSET }; if let Some(ty) = tcx.rcache.borrow().get(&key).cloned() { return Ok(ty); @@ -333,11 +333,6 @@ pub fn crate_rustc_version(data: &[u8]) -> Option { }) } -pub fn load_xrefs(data: &[u8]) -> index::DenseIndex { - let index = rbml::Doc::new(data).get(root_tag::xref_index); - index::DenseIndex::from_buf(index.data, index.start, index.end) -} - // Go through each item in the metadata and create a map from that // item's def-key to the item's DefIndex. pub fn load_key_map(data: &[u8]) -> FnvHashMap { @@ -1099,20 +1094,28 @@ fn doc_predicates<'a, 'tcx>(base_doc: rbml::Doc, { let mut dcx = base_doc.get(tag).decoder(); dcx.cdata = Some(cdata); + dcx.tcx = Some(tcx); ty::GenericPredicates { parent: dcx.decode(), - predicates: dcx.seq().map(|offset| { - let predicate_pos = cdata.xref_index.lookup( - cdata.data(), offset).unwrap() as usize; - let mut dcx = rbml::Doc { - data: cdata.data(), - start: predicate_pos, - end: cdata.data().len(), - }.decoder(); - dcx.tcx = Some(tcx); - dcx.cdata = Some(cdata); - dcx.decode() + predicates: (0..dcx.decode::()).map(|_| { + // Handle shorthands first, if we have an usize > 0x80. + if dcx.opaque.data[dcx.opaque.position()] & 0x80 != 0 { + let pos = dcx.decode::(); + assert!(pos >= SHORTHAND_OFFSET); + let pos = pos - SHORTHAND_OFFSET; + + let mut dcx = rbml::Doc { + data: cdata.data(), + start: pos, + end: cdata.data().len(), + }.decoder(); + dcx.tcx = Some(tcx); + dcx.cdata = Some(cdata); + dcx.decode() + } else { + dcx.decode() + } }).collect() } } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 3ad9251b07216..637228725e0be 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -16,7 +16,7 @@ use astencode::encode_inlined_item; use common::*; use cstore; -use index::{self, IndexData}; +use index::IndexData; use rustc::middle::cstore::{InlinedItemRef, LinkMeta, LinkagePreference}; use rustc::hir::def; @@ -30,11 +30,10 @@ use rustc::session::config::{self, CrateTypeRustcMacro}; use rustc::util::nodemap::{FnvHashMap, NodeSet}; use rustc_serialize::{Encodable, Encoder, SpecializedEncoder, opaque}; -use std::cell::RefCell; +use std::hash::Hash; use std::intrinsics; use std::io::prelude::*; use std::io::Cursor; -use std::mem; use std::ops::{Deref, DerefMut}; use std::rc::Rc; use std::u32; @@ -58,14 +57,10 @@ pub struct EncodeContext<'a, 'tcx: 'a> { reachable: &'a NodeSet, mir_map: &'a MirMap<'tcx>, - type_shorthands: RefCell, usize>>, - xrefs: FnvHashMap, u32>, // sequentially-assigned + type_shorthands: FnvHashMap, usize>, + predicate_shorthands: FnvHashMap, usize>, } -/// "interned" entries referenced by id -#[derive(PartialEq, Eq, Hash)] -enum XRef<'tcx> { Predicate(ty::Predicate<'tcx>) } - impl<'a, 'tcx> Deref for EncodeContext<'a, 'tcx> { type Target = rbml::writer::Encoder<'a>; fn deref(&self) -> &Self::Target { @@ -117,20 +112,49 @@ impl<'a, 'tcx> Encoder for EncodeContext<'a, 'tcx> { impl<'a, 'tcx> SpecializedEncoder> for EncodeContext<'a, 'tcx> { fn specialized_encode(&mut self, ty: &Ty<'tcx>) -> Result<(), Self::Error> { - let existing_shorthand = self.type_shorthands.borrow().get(ty).cloned(); + self.encode_with_shorthand(ty, &ty.sty, |ecx| &mut ecx.type_shorthands) + } +} + +impl<'a, 'tcx> EncodeContext<'a, 'tcx> { + fn seq(&mut self, iter: I, mut f: F) + where I: IntoIterator, + I::IntoIter: ExactSizeIterator, + F: FnMut(&mut Self, I::Item) -> T, + T: Encodable { + let iter = iter.into_iter(); + self.emit_seq(iter.len(), move |ecx| { + for (i, elem) in iter.enumerate() { + ecx.emit_seq_elt(i, |ecx| { + f(ecx, elem).encode(ecx) + })?; + } + Ok(()) + }).unwrap(); + } + + /// Encode the given value or a previously cached shorthand. + fn encode_with_shorthand(&mut self, value: &T, variant: &U, map: M) + -> Result<(), ::Error> + where M: for<'b> Fn(&'b mut Self) -> &'b mut FnvHashMap, + T: Clone + Eq + Hash, + U: Encodable { + let existing_shorthand = map(self).get(value).cloned(); if let Some(shorthand) = existing_shorthand { return self.emit_usize(shorthand); } let start = self.mark_stable_position(); - ty.sty.encode(self)?; + variant.encode(self)?; let len = self.mark_stable_position() - start; // The shorthand encoding uses the same usize as the // discriminant, with an offset so they can't conflict. - let discriminant = unsafe { intrinsics::discriminant_value(&ty.sty) }; - assert!(discriminant < TYPE_SHORTHAND_OFFSET as u64); - let shorthand = start + TYPE_SHORTHAND_OFFSET; + let discriminant = unsafe { + intrinsics::discriminant_value(variant) + }; + assert!(discriminant < SHORTHAND_OFFSET as u64); + let shorthand = start + SHORTHAND_OFFSET; // Get the number of bits that leb128 could fit // in the same space as the fully encoded type. @@ -139,29 +163,11 @@ impl<'a, 'tcx> SpecializedEncoder> for EncodeContext<'a, 'tcx> { // Check that the shorthand is a not longer than the // full encoding itself, i.e. it's an obvious win. if leb128_bits >= 64 || (shorthand as u64) < (1 << leb128_bits) { - self.type_shorthands.borrow_mut().insert(*ty, shorthand); + map(self).insert(value.clone(), shorthand); } Ok(()) } -} - -impl<'a, 'tcx> EncodeContext<'a, 'tcx> { - fn seq(&mut self, iter: I, mut f: F) - where I: IntoIterator, - I::IntoIter: ExactSizeIterator, - F: FnMut(&mut Self, I::Item) -> T, - T: Encodable { - let iter = iter.into_iter(); - self.emit_seq(iter.len(), move |ecx| { - for (i, elem) in iter.enumerate() { - ecx.emit_seq_elt(i, |ecx| { - f(ecx, elem).encode(ecx) - })?; - } - Ok(()) - }).unwrap(); - } /// For every DefId that we create a metadata item for, we include a /// serialized copy of its DefKey, which allows us to recreate a path. @@ -393,7 +399,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.start_tag(tag); predicates.parent.encode(self).unwrap(); self.seq(&predicates.predicates, |ecx, predicate| { - ecx.add_xref(XRef::Predicate(predicate.clone())) + ecx.encode_with_shorthand(predicate, predicate, + |ecx| &mut ecx.predicate_shorthands).unwrap() }); self.end_tag(); } @@ -575,34 +582,6 @@ fn encode_stability(ecx: &mut EncodeContext, def_id: DefId) { } impl<'a, 'tcx> EncodeContext<'a, 'tcx> { - fn add_xref(&mut self, xref: XRef<'tcx>) -> u32 { - let old_len = self.xrefs.len() as u32; - *self.xrefs.entry(xref).or_insert(old_len) - } - - fn encode_xrefs(&mut self) { - let xrefs = mem::replace(&mut self.xrefs, Default::default()); - let mut xref_positions = vec![0; xrefs.len()]; - - // Encode XRefs sorted by their ID - let mut sorted_xrefs: Vec<_> = xrefs.into_iter().collect(); - sorted_xrefs.sort_by_key(|&(_, id)| id); - - self.start_tag(root_tag::xref_data); - for (xref, id) in sorted_xrefs.into_iter() { - xref_positions[id as usize] = self.mark_stable_position() as u32; - match xref { - XRef::Predicate(p) => p.encode(self).unwrap() - } - } - self.mark_stable_position(); - self.end_tag(); - - self.start_tag(root_tag::xref_index); - index::write_dense_index(xref_positions, &mut self.opaque.cursor); - self.end_tag(); - } - fn encode_info_for_item(&mut self, (def_id, item): (DefId, &hir::Item)) { let tcx = self.tcx; @@ -1233,7 +1212,7 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, reachable: reachable, mir_map: mir_map, type_shorthands: Default::default(), - xrefs: Default::default() + predicate_shorthands: Default::default() }); // RBML compacts the encoded bytes whenever appropriate, @@ -1345,10 +1324,6 @@ fn encode_metadata_inner(ecx: &mut EncodeContext) { encode_item_index(ecx, items); let index_bytes = ecx.position() - i; - i = ecx.position(); - ecx.encode_xrefs(); - let xref_bytes = ecx.position() - i; - let total_bytes = ecx.position(); if ecx.tcx.sess.meta_stats() { @@ -1369,7 +1344,6 @@ fn encode_metadata_inner(ecx: &mut EncodeContext) { println!(" reachable bytes: {}", reachable_bytes); println!(" item bytes: {}", item_bytes); println!(" index bytes: {}", index_bytes); - println!(" xref bytes: {}", xref_bytes); println!(" zero bytes: {}", zero_bytes); println!(" total bytes: {}", total_bytes); } diff --git a/src/librustc_metadata/index.rs b/src/librustc_metadata/index.rs index 80d5141c99ca5..2c16411c37bdf 100644 --- a/src/librustc_metadata/index.rs +++ b/src/librustc_metadata/index.rs @@ -108,36 +108,6 @@ impl IndexData { } } -/// A dense index with integer keys. Different API from IndexData (should -/// these be merged?) -pub struct DenseIndex { - start: usize, - end: usize -} - -impl DenseIndex { - pub fn lookup(&self, buf: &[u8], ix: u32) -> Option { - let data = bytes_to_words(&buf[self.start..self.end]); - data.get(ix as usize).map(|d| u32::from_le(*d)) - } - pub fn from_buf(buf: &[u8], start: usize, end: usize) -> Self { - assert!((end-start)%4 == 0 && start <= end && end <= buf.len()); - DenseIndex { - start: start, - end: end - } - } -} - -pub fn write_dense_index(entries: Vec, buf: &mut Cursor>) { - let elen = entries.len(); - assert!(elen < u32::MAX as usize); - - buf.write_all(words_to_bytes(&entries)).unwrap(); - - info!("write_dense_index: {} entries", elen); -} - fn bytes_to_words(b: &[u8]) -> &[u32] { assert!(b.len() % 4 == 0); unsafe { slice::from_raw_parts(b.as_ptr() as *const u32, b.len()/4) } From adddfccf2b63f7969d80d459788e973b56168ec4 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Thu, 15 Sep 2016 11:04:00 +0300 Subject: [PATCH 26/39] rustc_metadata: move all encoding/decoding helpers to methods. --- src/librustc/middle/cstore.rs | 3 - src/librustc_metadata/astencode.rs | 6 +- src/librustc_metadata/creader.rs | 35 +- src/librustc_metadata/csearch.rs | 148 +-- src/librustc_metadata/cstore.rs | 22 +- src/librustc_metadata/decoder.rs | 1385 ++++++++++++-------------- src/librustc_metadata/encoder.rs | 443 ++++---- src/librustc_metadata/loader.rs | 13 +- src/librustc_metadata/rbml/reader.rs | 73 +- src/librustdoc/clean/mod.rs | 4 +- 10 files changed, 1002 insertions(+), 1130 deletions(-) diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 87fdc858cf0f5..6324995f328b9 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -188,7 +188,6 @@ pub trait CrateStore<'tcx> { fn is_compiler_builtins(&self, cnum: CrateNum) -> bool; fn panic_strategy(&self, cnum: CrateNum) -> PanicStrategy; fn extern_crate(&self, cnum: CrateNum) -> Option; - fn crate_attrs(&self, cnum: CrateNum) -> Vec; /// The name of the crate as it is referred to in source code of the current /// crate. fn crate_name(&self, cnum: CrateNum) -> InternedString; @@ -365,8 +364,6 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { bug!("panic_strategy") } fn extern_crate(&self, cnum: CrateNum) -> Option { bug!("extern_crate") } - fn crate_attrs(&self, cnum: CrateNum) -> Vec - { bug!("crate_attrs") } fn crate_name(&self, cnum: CrateNum) -> InternedString { bug!("crate_name") } fn original_crate_name(&self, cnum: CrateNum) -> InternedString { bug!("original_crate_name") diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs index 518e662441218..f48c31fc2f9dd 100644 --- a/src/librustc_metadata/astencode.rs +++ b/src/librustc_metadata/astencode.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![allow(non_camel_case_types)] - use rustc::hir::map as ast_map; use rustc::hir::intravisit::{Visitor, IdRangeComputingVisitor, IdRange}; @@ -64,9 +62,7 @@ pub fn decode_inlined_item<'a, 'tcx>(cdata: &CrateMetadata, orig_did: DefId) -> &'tcx InlinedItem { debug!("> Decoding inlined fn: {:?}", tcx.item_path_str(orig_did)); - let dcx = &mut ast_doc.decoder(); - dcx.tcx = Some(tcx); - dcx.cdata = Some(cdata); + let dcx = &mut DecodeContext::new(ast_doc, Some(cdata)).typed(tcx); dcx.from_id_range = IdRange::decode(dcx).unwrap(); let cnt = dcx.from_id_range.max.as_usize() - dcx.from_id_range.min.as_usize(); dcx.to_id_range.min = tcx.sess.reserve_node_ids(cnt); diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 73dcf9470183b..77a583f7379c1 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -14,7 +14,6 @@ use common::CrateInfo; use cstore::{self, CStore, CrateSource, MetadataBlob}; -use decoder; use loader::{self, CratePaths}; use rustc::hir::def_id::{CrateNum, DefIndex}; @@ -28,6 +27,7 @@ use rustc::util::nodemap::{FnvHashMap, FnvHashSet}; use rustc::hir::map as hir_map; use std::cell::{RefCell, Cell}; +use std::ops::Deref; use std::path::PathBuf; use std::rc::Rc; use std::fs; @@ -143,11 +143,13 @@ enum PMDSource { Owned(loader::Library), } -impl PMDSource { - pub fn as_slice<'a>(&'a self) -> &'a [u8] { +impl Deref for PMDSource { + type Target = MetadataBlob; + + fn deref(&self) -> &MetadataBlob { match *self { - PMDSource::Registered(ref cmd) => cmd.data(), - PMDSource::Owned(ref lib) => lib.metadata.as_slice(), + PMDSource::Registered(ref cmd) => &cmd.data, + PMDSource::Owned(ref lib) => &lib.metadata } } } @@ -295,7 +297,7 @@ impl<'a> CrateReader<'a> { -> (CrateNum, Rc, cstore::CrateSource) { info!("register crate `extern crate {} as {}`", name, ident); - let crate_info = decoder::get_crate_info(lib.metadata.as_slice()); + let crate_info = lib.metadata.get_crate_info(); self.verify_no_symbol_conflicts(span, &crate_info); // Claim this crate number and cache it @@ -317,7 +319,7 @@ impl<'a> CrateReader<'a> { let loader::Library { dylib, rlib, metadata } = lib; - let cnum_map = self.resolve_crate_deps(root, metadata.as_slice(), cnum, span); + let cnum_map = self.resolve_crate_deps(root, &metadata, cnum, span); if crate_info.macro_derive_registrar.is_some() { self.sess.span_err(span, "crates of the `rustc-macro` crate type \ @@ -328,8 +330,8 @@ impl<'a> CrateReader<'a> { name: name.to_string(), extern_crate: Cell::new(None), info: crate_info, - index: decoder::load_index(metadata.as_slice()), - key_map: decoder::load_key_map(metadata.as_slice()), + index: metadata.load_index(), + key_map: metadata.load_key_map(), data: metadata, cnum_map: RefCell::new(cnum_map), cnum: cnum, @@ -414,7 +416,7 @@ impl<'a> CrateReader<'a> { // Note that we only do this for target triple crates, though, as we // don't want to match a host crate against an equivalent target one // already loaded. - let crate_info = decoder::get_crate_info(library.metadata.as_slice()); + let crate_info = library.metadata.get_crate_info(); if loader.triple == self.sess.opts.target_triple { let mut result = LoadResult::Loaded(library); self.cstore.iter_crate_data(|cnum, data| { @@ -465,14 +467,14 @@ impl<'a> CrateReader<'a> { // Go through the crate metadata and load any crates that it references fn resolve_crate_deps(&mut self, root: &Option, - cdata: &[u8], + metadata: &MetadataBlob, krate: CrateNum, span: Span) -> cstore::CrateNumMap { debug!("resolving deps of external crate"); // The map from crate numbers in the crate we're resolving to local crate // numbers - let map: FnvHashMap<_, _> = decoder::get_crate_deps(cdata).iter().map(|dep| { + let map: FnvHashMap<_, _> = metadata.get_crate_deps().iter().map(|dep| { debug!("resolving dep crate {} hash: `{}`", dep.name, dep.hash); let (local_cnum, ..) = self.resolve_crate(root, &dep.name, @@ -566,7 +568,7 @@ impl<'a> CrateReader<'a> { let ci = self.extract_crate_info(item).unwrap(); let ekrate = self.read_extension_crate(item.span, &ci); - let crate_info = decoder::get_crate_info(ekrate.metadata.as_slice()); + let crate_info = ekrate.metadata.get_crate_info(); let source_name = format!("<{} macros>", item.ident); let mut ret = Macros { macro_rules: Vec::new(), @@ -574,8 +576,7 @@ impl<'a> CrateReader<'a> { svh: crate_info.hash, dylib: None, }; - decoder::each_exported_macro(ekrate.metadata.as_slice(), - |name, attrs, span, body| { + ekrate.metadata.each_exported_macro(|name, attrs, span, body| { // NB: Don't use parse::parse_tts_from_source_str because it parses with // quote_depth > 0. let mut p = parse::new_parser_from_source_str(&self.sess.parse_sess, @@ -670,7 +671,7 @@ impl<'a> CrateReader<'a> { span_fatal!(self.sess, span, E0456, "{}", &message[..]); } - let crate_info = decoder::get_crate_info(ekrate.metadata.as_slice()); + let crate_info = ekrate.metadata.get_crate_info(); match (ekrate.dylib.as_ref(), crate_info.plugin_registrar_fn) { (Some(dylib), Some(reg)) => { Some((dylib.to_path_buf(), crate_info.hash, reg)) @@ -1111,7 +1112,7 @@ pub fn read_local_crates(sess: & Session, pub fn import_codemap(local_codemap: &codemap::CodeMap, metadata: &MetadataBlob) -> Vec { - let external_codemap = decoder::get_imported_filemaps(metadata.as_slice()); + let external_codemap = metadata.get_imported_filemaps(); let imported_filemaps = external_codemap.into_iter().map(|filemap_to_import| { // Try to find an existing FileMap that can be reused for the filemap to diff --git a/src/librustc_metadata/csearch.rs b/src/librustc_metadata/csearch.rs index f650155c03546..8136fc7e845f3 100644 --- a/src/librustc_metadata/csearch.rs +++ b/src/librustc_metadata/csearch.rs @@ -10,7 +10,6 @@ use cstore; use common; -use decoder; use encoder; use loader; @@ -40,101 +39,87 @@ use rustc::hir; impl<'tcx> CrateStore<'tcx> for cstore::CStore { fn stability(&self, def: DefId) -> Option { self.dep_graph.read(DepNode::MetaData(def)); - let cdata = self.get_crate_data(def.krate); - decoder::get_stability(&cdata, def.index) + self.get_crate_data(def.krate).get_stability(def.index) } fn deprecation(&self, def: DefId) -> Option { self.dep_graph.read(DepNode::MetaData(def)); - let cdata = self.get_crate_data(def.krate); - decoder::get_deprecation(&cdata, def.index) + self.get_crate_data(def.krate).get_deprecation(def.index) } fn visibility(&self, def: DefId) -> ty::Visibility { self.dep_graph.read(DepNode::MetaData(def)); - let cdata = self.get_crate_data(def.krate); - decoder::get_visibility(&cdata, def.index) + self.get_crate_data(def.krate).get_visibility(def.index) } fn closure_kind(&self, def_id: DefId) -> ty::ClosureKind { assert!(!def_id.is_local()); self.dep_graph.read(DepNode::MetaData(def_id)); - let cdata = self.get_crate_data(def_id.krate); - decoder::closure_kind(&cdata, def_id.index) + self.get_crate_data(def_id.krate).closure_kind(def_id.index) } fn closure_ty<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> ty::ClosureTy<'tcx> { assert!(!def_id.is_local()); self.dep_graph.read(DepNode::MetaData(def_id)); - let cdata = self.get_crate_data(def_id.krate); - decoder::closure_ty(&cdata, def_id.index, tcx) + self.get_crate_data(def_id.krate).closure_ty(def_id.index, tcx) } fn item_variances(&self, def: DefId) -> Vec { self.dep_graph.read(DepNode::MetaData(def)); - let cdata = self.get_crate_data(def.krate); - decoder::get_item_variances(&cdata, def.index) + self.get_crate_data(def.krate).get_item_variances(def.index) } fn item_type<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> Ty<'tcx> { self.dep_graph.read(DepNode::MetaData(def)); - let cdata = self.get_crate_data(def.krate); - decoder::get_type(&cdata, def.index, tcx) + self.get_crate_data(def.krate).get_type(def.index, tcx) } fn item_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> ty::GenericPredicates<'tcx> { self.dep_graph.read(DepNode::MetaData(def)); - let cdata = self.get_crate_data(def.krate); - decoder::get_predicates(&cdata, def.index, tcx) + self.get_crate_data(def.krate).get_predicates(def.index, tcx) } fn item_super_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> ty::GenericPredicates<'tcx> { self.dep_graph.read(DepNode::MetaData(def)); - let cdata = self.get_crate_data(def.krate); - decoder::get_super_predicates(&cdata, def.index, tcx) + self.get_crate_data(def.krate).get_super_predicates(def.index, tcx) } fn item_generics<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> &'tcx ty::Generics<'tcx> { self.dep_graph.read(DepNode::MetaData(def)); - let cdata = self.get_crate_data(def.krate); - decoder::get_generics(&cdata, def.index, tcx) + self.get_crate_data(def.krate).get_generics(def.index, tcx) } fn item_attrs(&self, def_id: DefId) -> Vec { self.dep_graph.read(DepNode::MetaData(def_id)); - let cdata = self.get_crate_data(def_id.krate); - decoder::get_item_attrs(&cdata, def_id.index) + self.get_crate_data(def_id.krate).get_item_attrs(def_id.index) } fn trait_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> ty::TraitDef<'tcx> { self.dep_graph.read(DepNode::MetaData(def)); - let cdata = self.get_crate_data(def.krate); - decoder::get_trait_def(&cdata, def.index, tcx) + self.get_crate_data(def.krate).get_trait_def(def.index, tcx) } fn adt_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> ty::AdtDefMaster<'tcx> { self.dep_graph.read(DepNode::MetaData(def)); - let cdata = self.get_crate_data(def.krate); - decoder::get_adt_def(&cdata, def.index, tcx) + self.get_crate_data(def.krate).get_adt_def(def.index, tcx) } fn fn_arg_names(&self, did: DefId) -> Vec { self.dep_graph.read(DepNode::MetaData(did)); - let cdata = self.get_crate_data(did.krate); - decoder::get_fn_arg_names(&cdata, did.index) + self.get_crate_data(did.krate).get_fn_arg_names(did.index) } fn opt_item_name(&self, def: DefId) -> Option { @@ -143,7 +128,7 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { if def.index == CRATE_DEF_INDEX { Some(token::intern(&cdata.name())) } else { - decoder::maybe_get_item_name(&cdata, def.index) + cdata.maybe_get_item_name(def.index) } } @@ -151,9 +136,8 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { { self.dep_graph.read(DepNode::MetaData(def_id)); let mut result = vec![]; - let cdata = self.get_crate_data(def_id.krate); - decoder::each_inherent_implementation_for_type(&cdata, def_id.index, - |iid| result.push(iid)); + self.get_crate_data(def_id.krate) + .each_inherent_implementation_for_type(def_id.index, |iid| result.push(iid)); result } @@ -164,7 +148,7 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { } let mut result = vec![]; self.iter_crate_data(|_, cdata| { - decoder::each_implementation_for_trait(cdata, filter, &mut |iid| { + cdata.each_implementation_for_trait(filter, &mut |iid| { result.push(iid) }) }); @@ -174,85 +158,74 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { fn impl_or_trait_items(&self, def_id: DefId) -> Vec { self.dep_graph.read(DepNode::MetaData(def_id)); let mut result = vec![]; - let crate_data = self.get_crate_data(def_id.krate); let get_crate_data = &mut |cnum| self.get_crate_data(cnum); - decoder::each_child_of_item(&crate_data, def_id.index, get_crate_data, - &mut |def, _, _| result.push(def.def_id())); + self.get_crate_data(def_id.krate) + .each_child_of_item(def_id.index, get_crate_data, + &mut |def, _, _| result.push(def.def_id())); result } fn impl_polarity(&self, def: DefId) -> hir::ImplPolarity { self.dep_graph.read(DepNode::MetaData(def)); - let cdata = self.get_crate_data(def.krate); - decoder::get_impl_polarity(&cdata, def.index) + self.get_crate_data(def.krate).get_impl_polarity(def.index) } fn impl_trait_ref<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> Option> { self.dep_graph.read(DepNode::MetaData(def)); - let cdata = self.get_crate_data(def.krate); - decoder::get_impl_trait(&cdata, def.index, tcx) + self.get_crate_data(def.krate).get_impl_trait(def.index, tcx) } fn custom_coerce_unsized_kind(&self, def: DefId) -> Option { self.dep_graph.read(DepNode::MetaData(def)); - let cdata = self.get_crate_data(def.krate); - decoder::get_custom_coerce_unsized_kind(&cdata, def.index) + self.get_crate_data(def.krate).get_custom_coerce_unsized_kind(def.index) } fn impl_parent(&self, impl_def: DefId) -> Option { self.dep_graph.read(DepNode::MetaData(impl_def)); - let cdata = self.get_crate_data(impl_def.krate); - decoder::get_parent_impl(&*cdata, impl_def.index) + self.get_crate_data(impl_def.krate).get_parent_impl(impl_def.index) } fn trait_of_item(&self, def_id: DefId) -> Option { self.dep_graph.read(DepNode::MetaData(def_id)); - let cdata = self.get_crate_data(def_id.krate); - decoder::get_trait_of_item(&cdata, def_id.index) + self.get_crate_data(def_id.krate).get_trait_of_item(def_id.index) } fn impl_or_trait_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> Option> { self.dep_graph.read(DepNode::MetaData(def)); - let cdata = self.get_crate_data(def.krate); - decoder::get_impl_or_trait_item(&cdata, def.index, tcx) + self.get_crate_data(def.krate).get_impl_or_trait_item(def.index, tcx) } fn is_const_fn(&self, did: DefId) -> bool { self.dep_graph.read(DepNode::MetaData(did)); - let cdata = self.get_crate_data(did.krate); - decoder::is_const_fn(&cdata, did.index) + self.get_crate_data(did.krate).is_const_fn(did.index) } fn is_defaulted_trait(&self, trait_def_id: DefId) -> bool { self.dep_graph.read(DepNode::MetaData(trait_def_id)); - let cdata = self.get_crate_data(trait_def_id.krate); - decoder::is_defaulted_trait(&cdata, trait_def_id.index) + self.get_crate_data(trait_def_id.krate).is_defaulted_trait(trait_def_id.index) } fn is_default_impl(&self, impl_did: DefId) -> bool { self.dep_graph.read(DepNode::MetaData(impl_did)); - let cdata = self.get_crate_data(impl_did.krate); - decoder::is_default_impl(&cdata, impl_did.index) + self.get_crate_data(impl_did.krate).is_default_impl(impl_did.index) } fn is_extern_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, did: DefId) -> bool { self.dep_graph.read(DepNode::MetaData(did)); - let cdata = self.get_crate_data(did.krate); - decoder::is_extern_item(&cdata, did.index, tcx) + self.get_crate_data(did.krate).is_extern_item(did.index, tcx) } fn is_foreign_item(&self, did: DefId) -> bool { - let cdata = self.get_crate_data(did.krate); - decoder::is_foreign_item(&cdata, did.index) + self.get_crate_data(did.krate).is_foreign_item(did.index) } fn is_statically_included_foreign_item(&self, id: ast::NodeId) -> bool @@ -263,21 +236,18 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { fn dylib_dependency_formats(&self, cnum: CrateNum) -> Vec<(CrateNum, LinkagePreference)> { - let cdata = self.get_crate_data(cnum); - decoder::get_dylib_dependency_formats(&cdata) + self.get_crate_data(cnum).get_dylib_dependency_formats() } fn lang_items(&self, cnum: CrateNum) -> Vec<(DefIndex, usize)> { - let crate_data = self.get_crate_data(cnum); - decoder::get_lang_items(&crate_data) + self.get_crate_data(cnum).get_lang_items() } fn missing_lang_items(&self, cnum: CrateNum) -> Vec { - let cdata = self.get_crate_data(cnum); - decoder::get_missing_lang_items(&cdata) + self.get_crate_data(cnum).get_missing_lang_items() } fn is_staged_api(&self, cnum: CrateNum) -> bool @@ -308,11 +278,6 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { self.get_crate_data(cnum).panic_strategy() } - fn crate_attrs(&self, cnum: CrateNum) -> Vec - { - decoder::get_item_attrs(&self.get_crate_data(cnum), CRATE_DEF_INDEX) - } - fn crate_name(&self, cnum: CrateNum) -> token::InternedString { token::intern_and_get_ident(&self.get_crate_data(cnum).name[..]) @@ -348,18 +313,16 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { fn native_libraries(&self, cnum: CrateNum) -> Vec<(NativeLibraryKind, String)> { - let cdata = self.get_crate_data(cnum); - decoder::get_native_libraries(&cdata) + self.get_crate_data(cnum).get_native_libraries() } fn reachable_ids(&self, cnum: CrateNum) -> Vec { - let cdata = self.get_crate_data(cnum); - decoder::get_reachable_ids(&cdata) + self.get_crate_data(cnum).get_reachable_ids() } fn is_no_builtins(&self, cnum: CrateNum) -> bool { - attr::contains_name(&self.crate_attrs(cnum), "no_builtins") + self.get_crate_data(cnum).is_no_builtins() } fn def_index_for_def_key(&self, @@ -380,8 +343,7 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { // canonical name for an item. // // self.dep_graph.read(DepNode::MetaData(def)); - let cdata = self.get_crate_data(def.krate); - decoder::def_key(&cdata, def.index) + self.get_crate_data(def.krate).def_key(def.index) } fn relative_def_path(&self, def: DefId) -> Option { @@ -389,34 +351,35 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { // commented out: // // self.dep_graph.read(DepNode::MetaData(def)); - let cdata = self.get_crate_data(def.krate); - decoder::def_path(&cdata, def.index) + self.get_crate_data(def.krate).def_path(def.index) } fn struct_ctor_def_id(&self, struct_def_id: DefId) -> Option { self.dep_graph.read(DepNode::MetaData(struct_def_id)); - let cdata = self.get_crate_data(struct_def_id.krate); - decoder::get_struct_ctor_def_id(&cdata, struct_def_id.index) + self.get_crate_data(struct_def_id.krate).get_struct_ctor_def_id(struct_def_id.index) } fn struct_field_names(&self, def: DefId) -> Vec { self.dep_graph.read(DepNode::MetaData(def)); - let cdata = self.get_crate_data(def.krate); - decoder::get_struct_field_names(&cdata, def.index) + self.get_crate_data(def.krate).get_struct_field_names(def.index) } fn item_children(&self, def_id: DefId) -> Vec { self.dep_graph.read(DepNode::MetaData(def_id)); let mut result = vec![]; - let crate_data = self.get_crate_data(def_id.krate); let get_crate_data = &mut |cnum| self.get_crate_data(cnum); - decoder::each_child_of_item(&crate_data, def_id.index, get_crate_data, - &mut |def, name, vis| { - result.push(ChildItem { def: def, name: name, vis: vis }); - }); + self.get_crate_data(def_id.krate) + .each_child_of_item(def_id.index, get_crate_data, + &mut |def, name, vis| { + result.push(ChildItem { + def: def, + name: name, + vis: vis + }); + }); result } @@ -445,8 +408,7 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { debug!("maybe_get_item_ast({}): inlining item", tcx.item_path_str(def_id)); - let cdata = self.get_crate_data(def_id.krate); - let inlined = decoder::maybe_get_item_ast(&cdata, tcx, def_id.index); + let inlined = self.get_crate_data(def_id.krate).maybe_get_item_ast(tcx, def_id.index); let cache_inlined_item = |original_def_id, inlined_item_id, inlined_root_node_id| { let cache_entry = cstore::CachedInlinedItem { @@ -534,14 +496,12 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { fn maybe_get_item_mir<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> Option> { self.dep_graph.read(DepNode::MetaData(def)); - let cdata = self.get_crate_data(def.krate); - decoder::maybe_get_item_mir(&cdata, tcx, def.index) + self.get_crate_data(def.krate).maybe_get_item_mir(tcx, def.index) } fn is_item_mir_available(&self, def: DefId) -> bool { self.dep_graph.read(DepNode::MetaData(def)); - let cdata = self.get_crate_data(def.krate); - decoder::is_item_mir_available(&cdata, def.index) + self.get_crate_data(def.krate).is_item_mir_available(def.index) } fn crates(&self) -> Vec diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index 44fdf29aa73c4..4151f98b3daee 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![allow(non_camel_case_types)] - // The crate store - a central repo for information collected about external // crates and libraries @@ -17,7 +15,6 @@ pub use self::MetadataBlob::*; use common; use creader; -use decoder; use index; use loader; @@ -297,7 +294,6 @@ impl CStore { } impl CrateMetadata { - pub fn data<'a>(&'a self) -> &'a [u8] { self.data.as_slice() } pub fn name(&self) -> &str { &self.info.name } pub fn hash(&self) -> Svh { self.info.hash } pub fn disambiguator(&self) -> &str { &self.info.disambiguator } @@ -317,37 +313,41 @@ impl CrateMetadata { } pub fn is_staged_api(&self) -> bool { - let attrs = decoder::get_item_attrs(self, CRATE_DEF_INDEX); - attrs.iter().any(|attr| { + self.get_item_attrs(CRATE_DEF_INDEX).iter().any(|attr| { attr.name() == "stable" || attr.name() == "unstable" }) } pub fn is_allocator(&self) -> bool { - let attrs = decoder::get_item_attrs(self, CRATE_DEF_INDEX); + let attrs = self.get_item_attrs(CRATE_DEF_INDEX); attr::contains_name(&attrs, "allocator") } pub fn needs_allocator(&self) -> bool { - let attrs = decoder::get_item_attrs(self, CRATE_DEF_INDEX); + let attrs = self.get_item_attrs(CRATE_DEF_INDEX); attr::contains_name(&attrs, "needs_allocator") } pub fn is_panic_runtime(&self) -> bool { - let attrs = decoder::get_item_attrs(self, CRATE_DEF_INDEX); + let attrs = self.get_item_attrs(CRATE_DEF_INDEX); attr::contains_name(&attrs, "panic_runtime") } pub fn needs_panic_runtime(&self) -> bool { - let attrs = decoder::get_item_attrs(self, CRATE_DEF_INDEX); + let attrs = self.get_item_attrs(CRATE_DEF_INDEX); attr::contains_name(&attrs, "needs_panic_runtime") } pub fn is_compiler_builtins(&self) -> bool { - let attrs = decoder::get_crate_attributes(self.data()); + let attrs = self.get_item_attrs(CRATE_DEF_INDEX); attr::contains_name(&attrs, "compiler_builtins") } + pub fn is_no_builtins(&self) -> bool { + let attrs = self.get_item_attrs(CRATE_DEF_INDEX); + attr::contains_name(&attrs, "no_builtins") + } + pub fn panic_strategy(&self) -> PanicStrategy { self.info.panic_strategy.clone() } diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index c665a7be955dc..05bd9e97234e5 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -10,14 +10,11 @@ // Decoding metadata from a single crate's metadata -#![allow(non_camel_case_types)] - use astencode::decode_inlined_item; -use cstore::{self, CrateMetadata}; +use cstore::{CrateMetadata, MetadataBlob, NativeLibraryKind}; use common::*; use index; -use rustc::hir::def_id::CRATE_DEF_INDEX; use rustc::hir::svh::Svh; use rustc::hir::map as hir_map; use rustc::hir::map::{DefKey, DefPathData}; @@ -43,7 +40,6 @@ use std::rc::Rc; use std::str; use std::u32; -use rbml::reader; use rbml; use rustc_serialize::{Decodable, Decoder, SpecializedDecoder, opaque}; use syntax::attr; @@ -53,37 +49,36 @@ use syntax_pos::{self, Span, BytePos}; pub struct DecodeContext<'a, 'tcx: 'a> { pub opaque: opaque::Decoder<'a>, - pub tcx: Option>, - pub cdata: Option<&'a cstore::CrateMetadata>, + tcx: Option>, + cdata: Option<&'a CrateMetadata>, pub from_id_range: IdRange, pub to_id_range: IdRange, // Cache the last used filemap for translating spans as an optimization. last_filemap_index: usize, } -impl<'doc> rbml::Doc<'doc> { - pub fn decoder<'tcx>(self) -> DecodeContext<'doc, 'tcx> { +impl<'a, 'tcx> DecodeContext<'a, 'tcx> { + pub fn new(doc: rbml::Doc<'a>, cdata: Option<&'a CrateMetadata>) + -> DecodeContext<'a, 'tcx> { let id_range = IdRange { min: NodeId::from_u32(u32::MIN), max: NodeId::from_u32(u32::MAX) }; DecodeContext { - opaque: opaque::Decoder::new(self.data, self.start), - cdata: None, + opaque: opaque::Decoder::new(doc.data, doc.start), + cdata: cdata, tcx: None, from_id_range: id_range, to_id_range: id_range, last_filemap_index: 0 } } -} -impl<'a, 'tcx> DecodeContext<'a, 'tcx> { pub fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> { self.tcx.expect("missing TyCtxt in DecodeContext") } - pub fn cdata(&self) -> &'a cstore::CrateMetadata { + pub fn cdata(&self) -> &'a CrateMetadata { self.cdata.expect("missing CrateMetadata in DecodeContext") } @@ -91,6 +86,11 @@ impl<'a, 'tcx> DecodeContext<'a, 'tcx> { T::decode(self).unwrap() } + pub fn typed(mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Self { + self.tcx = Some(tcx); + self + } + /// Iterate over the indices of a sequence. /// This will work solely because of `serialize::opaque`'s /// simple encoding of `n: usize` followed by `n` elements. @@ -295,124 +295,84 @@ impl<'a, 'tcx> SpecializedDecoder> for DecodeContext<'a, 'tcx> } } -pub type Cmd<'a> = &'a CrateMetadata; +#[derive(Clone)] +pub struct CrateDep { + pub cnum: CrateNum, + pub name: String, + pub hash: Svh, + pub explicitly_linked: bool, +} -impl CrateMetadata { - fn get_item(&self, item_id: DefIndex) -> Option { - self.index.lookup_item(self.data(), item_id).map(|pos| { - rbml::Doc::at(self.data(), pos as usize) - }) +impl<'a, 'tcx> MetadataBlob { + fn root(&self) -> rbml::Doc { + rbml::Doc::new(self.as_slice()) } - fn lookup_item(&self, item_id: DefIndex) -> rbml::Doc { - match self.get_item(item_id) { - None => bug!("lookup_item: id not found: {:?} in crate {:?} with number {}", - item_id, - self.name, - self.cnum), - Some(d) => d - } + fn child_at(&'a self, pos: usize, tag: usize) -> DecodeContext<'a, 'tcx> { + DecodeContext::new(rbml::Doc::at(self.as_slice(), pos).child(tag), None) } - fn local_def_id(&self, index: DefIndex) -> DefId { - DefId { - krate: self.cnum, - index: index - } + fn get(&'a self, tag: usize) -> DecodeContext<'a, 'tcx> { + DecodeContext::new(self.root().child(tag), None) } -} - -pub fn load_index(data: &[u8]) -> index::Index { - index::Index::from_rbml(rbml::Doc::new(data).get(root_tag::index)) -} - -pub fn crate_rustc_version(data: &[u8]) -> Option { - let doc = rbml::Doc::new(data); - reader::maybe_get_doc(doc, root_tag::rustc_version).map(|s| { - str::from_utf8(&s.data[s.start..s.end]).unwrap().to_string() - }) -} - -// Go through each item in the metadata and create a map from that -// item's def-key to the item's DefIndex. -pub fn load_key_map(data: &[u8]) -> FnvHashMap { - load_index(data).iter_enumerated(data).map(|(index, pos)| { - // load def-key from item - let key = item_def_key(rbml::Doc::at(data, pos as usize)); - (key, index) - }).collect() -} - -fn item_family(item: rbml::Doc) -> Family { - item.get(item_tag::family).decoder().decode() -} -fn item_visibility(item: rbml::Doc) -> ty::Visibility { - item.get(item_tag::visibility).decoder().decode() -} - -fn entry_data(doc: rbml::Doc, cdata: Cmd) -> EntryData { - let mut dcx = doc.get(item_tag::data).decoder(); - dcx.cdata = Some(cdata); + pub fn load_index(&self) -> index::Index { + index::Index::from_rbml(self.root().child(root_tag::index)) + } - dcx.decode() -} + pub fn crate_rustc_version(&self) -> Option { + self.root().maybe_child(root_tag::rustc_version).map(|s| { + str::from_utf8(&s.data[s.start..s.end]).unwrap().to_string() + }) + } -fn entry_typed_data<'a, 'tcx>(doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>, cdata: Cmd) - -> EntryTypedData<'tcx> { - let mut dcx = doc.get(item_tag::typed_data).decoder(); - dcx.cdata = Some(cdata); - dcx.tcx = Some(tcx); + // Go through each item in the metadata and create a map from that + // item's def-key to the item's DefIndex. + pub fn load_key_map(&self) -> FnvHashMap { + self.load_index().iter_enumerated(self.as_slice()).map(|(index, pos)| { + (self.child_at(pos as usize, item_tag::def_key).decode(), index) + }).collect() + } - dcx.decode() -} + pub fn get_crate_deps(&self) -> Vec { + let dcx = self.get(root_tag::crate_deps); -fn item_parent_item(cdata: Cmd, d: rbml::Doc) -> Option { - item_def_key(d).parent.map(|index| cdata.local_def_id(index)) -} + dcx.seq().enumerate().map(|(crate_num, (name, hash, explicitly_linked))| { + CrateDep { + cnum: CrateNum::new(crate_num + 1), + name: name, + hash: hash, + explicitly_linked: explicitly_linked, + } + }).collect() + } -fn doc_type<'a, 'tcx>(doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>, cdata: Cmd) -> Ty<'tcx> { - maybe_doc_type(doc, tcx, cdata).expect("missing item_tag::ty") -} + pub fn get_crate_info(&self) -> CrateInfo { + self.get(root_tag::crate_info).decode() + } -fn maybe_doc_type<'a, 'tcx>(doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>, cdata: Cmd) - -> Option> { - reader::maybe_get_doc(doc, item_tag::ty).map(|tp| { - let mut dcx = tp.decoder(); - dcx.tcx = Some(tcx); - dcx.cdata = Some(cdata); - dcx.decode() - }) -} + pub fn list_crate_metadata(&self, out: &mut io::Write) -> io::Result<()> { + write!(out, "=External Dependencies=\n")?; + for dep in &self.get_crate_deps() { + write!(out, "{} {}-{}\n", dep.cnum, dep.name, dep.hash)?; + } + write!(out, "\n")?; + Ok(()) + } -fn item_name(item: rbml::Doc) -> ast::Name { - maybe_item_name(item).expect("no item in item_name") -} + pub fn get_imported_filemaps(&self) -> Vec { + self.get(root_tag::codemap).decode() + } -fn maybe_item_name(item: rbml::Doc) -> Option { - let name = match item_def_key(item).disambiguated_data.data { - DefPathData::TypeNs(name) | - DefPathData::ValueNs(name) | - DefPathData::Module(name) | - DefPathData::MacroDef(name) | - DefPathData::TypeParam(name) | - DefPathData::LifetimeDef(name) | - DefPathData::EnumVariant(name) | - DefPathData::Field(name) | - DefPathData::Binding(name) => Some(name), - - DefPathData::InlinedRoot(_) => bug!("unexpected DefPathData"), - - DefPathData::CrateRoot | - DefPathData::Misc | - DefPathData::Impl | - DefPathData::ClosureExpr | - DefPathData::StructCtor | - DefPathData::Initializer | - DefPathData::ImplTrait => None - }; - - name.map(|s| token::intern(&s)) + pub fn each_exported_macro(&self, mut f: F) where + F: FnMut(ast::Name, Vec, Span, String) -> bool, + { + for (name, attrs, span, body) in self.get(root_tag::macro_defs).seq() { + if !f(name, attrs, span, body) { + break; + } + } + } } impl Family { @@ -444,729 +404,698 @@ impl Family { } } -pub fn get_trait_def<'a, 'tcx>(cdata: Cmd, - item_id: DefIndex, - tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ty::TraitDef<'tcx> -{ - let item_doc = cdata.lookup_item(item_id); - let generics = doc_generics(item_doc, tcx, cdata); - - let data = match entry_data(item_doc, cdata) { - EntryData::Trait(data) => data, - _ => bug!() - }; - let typed_data = match entry_typed_data(item_doc, tcx, cdata) { - EntryTypedData::Trait(data) => data, - _ => bug!() - }; - - ty::TraitDef::new(data.unsafety, data.paren_sugar, generics, typed_data.trait_ref, - def_path(cdata, item_id).unwrap().deterministic_hash(tcx))) -} - -fn get_variant<'tcx>(cdata: Cmd, - item: rbml::Doc, - index: DefIndex) - -> (ty::VariantDefData<'tcx, 'tcx>, Option) { - let data = match entry_data(item, cdata) { - EntryData::Variant(data) => data, - _ => bug!() - }; - - let mut dcx = item.get(item_tag::children).decoder(); - dcx.cdata = Some(cdata); - - let fields = dcx.seq().map(|index| { - let f = cdata.lookup_item(index); - ty::FieldDefData::new(cdata.local_def_id(index), - item_name(f), - item_visibility(f)) - }).collect(); - - (ty::VariantDefData { - did: cdata.local_def_id(data.struct_ctor.unwrap_or(index)), - name: item_name(item), - fields: fields, - disr_val: ConstInt::Infer(data.disr), - kind: data.kind, - }, data.struct_ctor) -} +impl<'a, 'tcx> CrateMetadata { + fn maybe_get(&'a self, item: rbml::Doc<'a>, tag: usize) + -> Option> { + item.maybe_child(tag).map(|child| { + DecodeContext::new(child, Some(self)) + }) + } -pub fn get_adt_def<'a, 'tcx>(cdata: Cmd, - item_id: DefIndex, - tcx: TyCtxt<'a, 'tcx, 'tcx>) - -> ty::AdtDefMaster<'tcx> -{ - let doc = cdata.lookup_item(item_id); - let did = cdata.local_def_id(item_id); - let mut ctor_index = None; - let family = item_family(doc); - let variants = if family == Family::Enum { - let mut dcx = doc.get(item_tag::children).decoder(); - dcx.cdata = Some(cdata); - - dcx.seq().map(|index| { - let (variant, struct_ctor) = get_variant(cdata, cdata.lookup_item(index), index); - assert_eq!(struct_ctor, None); - variant - }).collect() - } else{ - let (variant, struct_ctor) = get_variant(cdata, doc, item_id); - ctor_index = struct_ctor; - vec![variant] - }; - let kind = match family { - Family::Enum => ty::AdtKind::Enum, - Family::Struct => ty::AdtKind::Struct, - Family::Union => ty::AdtKind::Union, - _ => bug!("get_adt_def called on a non-ADT {:?} - {:?}", - family, did) - }; - - let adt = tcx.intern_adt_def(did, kind, variants); - if let Some(ctor_index) = ctor_index { - // Make adt definition available through constructor id as well. - tcx.insert_adt_def(cdata.local_def_id(ctor_index), adt); - } - - // this needs to be done *after* the variant is interned, - // to support recursive structures - for variant in &adt.variants { - for field in &variant.fields { - debug!("evaluating the type of {:?}::{:?}", variant.name, field.name); - let ty = get_type(cdata, field.did.index, tcx); - field.fulfill_ty(ty); - debug!("evaluating the type of {:?}::{:?}: {:?}", - variant.name, field.name, ty); + fn get(&'a self, item: rbml::Doc<'a>, tag: usize) -> DecodeContext<'a, 'tcx> { + match self.maybe_get(item, tag) { + Some(dcx) => dcx, + None => bug!("failed to find child with tag {}", tag) } } - adt -} + fn item_family(&self, item: rbml::Doc) -> Family { + self.get(item, item_tag::family).decode() + } -pub fn get_predicates<'a, 'tcx>(cdata: Cmd, - item_id: DefIndex, - tcx: TyCtxt<'a, 'tcx, 'tcx>) - -> ty::GenericPredicates<'tcx> -{ - let item_doc = cdata.lookup_item(item_id); - doc_predicates(item_doc, tcx, cdata, item_tag::predicates) -} + fn item_visibility(&self, item: rbml::Doc) -> ty::Visibility { + self.get(item, item_tag::visibility).decode() + } -pub fn get_super_predicates<'a, 'tcx>(cdata: Cmd, - item_id: DefIndex, - tcx: TyCtxt<'a, 'tcx, 'tcx>) - -> ty::GenericPredicates<'tcx> -{ - let item_doc = cdata.lookup_item(item_id); - doc_predicates(item_doc, tcx, cdata, item_tag::super_predicates) -} + fn item_def_key(&self, item: rbml::Doc) -> hir_map::DefKey { + self.get(item, item_tag::def_key).decode() + } -pub fn get_generics<'a, 'tcx>(cdata: Cmd, - item_id: DefIndex, - tcx: TyCtxt<'a, 'tcx, 'tcx>) - -> &'tcx ty::Generics<'tcx> -{ - let item_doc = cdata.lookup_item(item_id); - doc_generics(item_doc, tcx, cdata) -} + fn item_name(&self, item: rbml::Doc) -> ast::Name { + self.maybe_item_name(item).expect("no item in item_name") + } -pub fn get_type<'a, 'tcx>(cdata: Cmd, id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) - -> Ty<'tcx> -{ - let item_doc = cdata.lookup_item(id); - doc_type(item_doc, tcx, cdata) -} + fn maybe_item_name(&self, item: rbml::Doc) -> Option { + let name = match self.item_def_key(item).disambiguated_data.data { + DefPathData::TypeNs(name) | + DefPathData::ValueNs(name) | + DefPathData::Module(name) | + DefPathData::MacroDef(name) | + DefPathData::TypeParam(name) | + DefPathData::LifetimeDef(name) | + DefPathData::EnumVariant(name) | + DefPathData::Field(name) | + DefPathData::Binding(name) => Some(name), + + DefPathData::InlinedRoot(_) => bug!("unexpected DefPathData"), + + DefPathData::CrateRoot | + DefPathData::Misc | + DefPathData::Impl | + DefPathData::ClosureExpr | + DefPathData::StructCtor | + DefPathData::Initializer | + DefPathData::ImplTrait => None + }; -pub fn get_stability(cdata: Cmd, id: DefIndex) -> Option { - let item = cdata.lookup_item(id); - reader::maybe_get_doc(item, item_tag::stability).map(|doc| { - doc.decoder().decode() - }) -} + name.map(|s| token::intern(&s)) + } -pub fn get_deprecation(cdata: Cmd, id: DefIndex) -> Option { - let item = cdata.lookup_item(id); - reader::maybe_get_doc(item, item_tag::deprecation).map(|doc| { - doc.decoder().decode() - }) -} + fn maybe_entry(&self, item_id: DefIndex) -> Option { + self.index.lookup_item(self.data.as_slice(), item_id).map(|pos| { + rbml::Doc::at(self.data.as_slice(), pos as usize) + }) + } -pub fn get_visibility(cdata: Cmd, id: DefIndex) -> ty::Visibility { - item_visibility(cdata.lookup_item(id)) -} + fn entry(&self, item_id: DefIndex) -> rbml::Doc { + match self.maybe_entry(item_id) { + None => bug!("entry: id not found: {:?} in crate {:?} with number {}", + item_id, + self.name, + self.cnum), + Some(d) => d + } + } -fn get_impl_data(cdata: Cmd, id: DefIndex) -> ImplData { - match entry_data(cdata.lookup_item(id), cdata) { - EntryData::Impl(data) => data, - _ => bug!() + fn local_def_id(&self, index: DefIndex) -> DefId { + DefId { + krate: self.cnum, + index: index + } } -} -pub fn get_parent_impl(cdata: Cmd, id: DefIndex) -> Option { - get_impl_data(cdata, id).parent_impl -} + fn entry_data(&self, doc: rbml::Doc) -> EntryData { + self.get(doc, item_tag::data).decode() + } -pub fn get_impl_polarity(cdata: Cmd, id: DefIndex) -> hir::ImplPolarity { - get_impl_data(cdata, id).polarity -} + fn entry_typed_data(&self, doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>) + -> EntryTypedData<'tcx> { + self.get(doc, item_tag::typed_data).typed(tcx).decode() + } -pub fn get_custom_coerce_unsized_kind( - cdata: Cmd, - id: DefIndex) - -> Option -{ - get_impl_data(cdata, id).coerce_unsized_kind -} + fn item_parent_item(&self, d: rbml::Doc) -> Option { + self.item_def_key(d).parent.map(|index| self.local_def_id(index)) + } -pub fn get_impl_trait<'a, 'tcx>(cdata: Cmd, - id: DefIndex, - tcx: TyCtxt<'a, 'tcx, 'tcx>) - -> Option> -{ - match entry_typed_data(cdata.lookup_item(id), tcx, cdata) { - EntryTypedData::Impl(data) => data.trait_ref, - _ => bug!() + fn doc_type(&self, doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx> { + self.maybe_doc_type(doc, tcx).expect("missing item_tag::ty") } -} -/// Iterates over the language items in the given crate. -pub fn get_lang_items(cdata: Cmd) -> Vec<(DefIndex, usize)> { - rbml::Doc::new(cdata.data()).get(root_tag::lang_items).decoder().decode() -} + fn maybe_doc_type(&self, doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option> { + self.maybe_get(doc, item_tag::ty).map(|dcx| dcx.typed(tcx).decode()) + } + pub fn get_trait_def(&self, + item_id: DefIndex, + tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ty::TraitDef<'tcx> { + let item_doc = self.entry(item_id); + let generics = self.doc_generics(item_doc, tcx); -/// Iterates over each child of the given item. -pub fn each_child_of_item(cdata: Cmd, id: DefIndex, - mut get_crate_data: &mut G, - mut callback: &mut F) - where F: FnMut(Def, ast::Name, ty::Visibility), - G: FnMut(CrateNum) -> Rc, -{ - // Find the item. - let item_doc = match cdata.get_item(id) { - None => return, - Some(item_doc) => item_doc, - }; - - let mut dcx = match reader::maybe_get_doc(item_doc, item_tag::children) { - Some(doc) => doc.decoder(), - None => return - }; - dcx.cdata = Some(cdata); - - // Iterate over all children. - for child_index in dcx.seq::() { - // Get the item. - if let Some(child) = cdata.get_item(child_index) { - // Hand off the item to the callback. - let family = item_family(child); - if let Family::ForeignMod = family { - each_child_of_item(cdata, child_index, get_crate_data, callback); - } else if let Some(def) = family.to_def(cdata.local_def_id(child_index)) { - callback(def, item_name(child), item_visibility(child)); - } - } + let data = match self.entry_data(item_doc) { + EntryData::Trait(data) => data, + _ => bug!() + }; + let typed_data = match self.entry_typed_data(item_doc, tcx) { + EntryTypedData::Trait(data) => data, + _ => bug!() + }; + + ty::TraitDef::new(data.unsafety, data.paren_sugar, generics, typed_data.trait_ref, + self.def_path(item_id).unwrap().deterministic_hash(tcx))) } - let reexports = match entry_data(item_doc, cdata) { - EntryData::Mod(data) => data.reexports, - _ => return - }; - for exp in reexports { - // This reexport may be in yet another crate. - let crate_data = if exp.def_id.krate == cdata.cnum { - None - } else { - Some(get_crate_data(exp.def_id.krate)) + fn get_variant(&self, item: rbml::Doc, index: DefIndex) + -> (ty::VariantDefData<'tcx, 'tcx>, Option) { + let data = match self.entry_data(item) { + EntryData::Variant(data) => data, + _ => bug!() }; - let crate_data = match crate_data { - Some(ref cdata) => &**cdata, - None => cdata + + let fields = self.get(item, item_tag::children).seq().map(|index| { + let f = self.entry(index); + ty::FieldDefData::new(self.local_def_id(index), + self.item_name(f), + self.item_visibility(f)) + }).collect(); + + (ty::VariantDefData { + did: self.local_def_id(data.struct_ctor.unwrap_or(index)), + name: self.item_name(item), + fields: fields, + disr_val: ConstInt::Infer(data.disr), + kind: data.kind, + }, data.struct_ctor) + } + + pub fn get_adt_def(&self, item_id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) + -> ty::AdtDefMaster<'tcx> { + let doc = self.entry(item_id); + let did = self.local_def_id(item_id); + let mut ctor_index = None; + let family = self.item_family(doc); + let variants = if family == Family::Enum { + self.get(doc, item_tag::children).seq().map(|index| { + let (variant, struct_ctor) = self.get_variant(self.entry(index), index); + assert_eq!(struct_ctor, None); + variant + }).collect() + } else{ + let (variant, struct_ctor) = self.get_variant(doc, item_id); + ctor_index = struct_ctor; + vec![variant] + }; + let kind = match family { + Family::Enum => ty::AdtKind::Enum, + Family::Struct => ty::AdtKind::Struct, + Family::Union => ty::AdtKind::Union, + _ => bug!("get_adt_def called on a non-ADT {:?} - {:?}", + family, did) }; - // Get the item. - if let Some(child) = crate_data.get_item(exp.def_id.index) { - // Hand off the item to the callback. - if let Some(def) = item_family(child).to_def(exp.def_id) { - // These items have a public visibility because they're part of - // a public re-export. - callback(def, exp.name, ty::Visibility::Public); + let adt = tcx.intern_adt_def(did, kind, variants); + if let Some(ctor_index) = ctor_index { + // Make adt definition available through constructor id as well. + tcx.insert_adt_def(self.local_def_id(ctor_index), adt); + } + + // this needs to be done *after* the variant is interned, + // to support recursive structures + for variant in &adt.variants { + for field in &variant.fields { + debug!("evaluating the type of {:?}::{:?}", variant.name, field.name); + let ty = self.get_type(field.did.index, tcx); + field.fulfill_ty(ty); + debug!("evaluating the type of {:?}::{:?}: {:?}", + variant.name, field.name, ty); } } + + adt } -} -pub fn maybe_get_item_name(cdata: Cmd, id: DefIndex) -> Option { - maybe_item_name(cdata.lookup_item(id)) -} + pub fn get_predicates(&self, item_id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) + -> ty::GenericPredicates<'tcx> { + self.doc_predicates(self.entry(item_id), tcx, item_tag::predicates) + } -pub fn maybe_get_item_ast<'a, 'tcx>(cdata: Cmd, tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefIndex) - -> Option<&'tcx InlinedItem> { - debug!("Looking up item: {:?}", id); - let item_doc = cdata.lookup_item(id); - let item_did = cdata.local_def_id(id); - let parent_def_id = cdata.local_def_id(def_key(cdata, id).parent.unwrap()); - let mut parent_def_path = def_path(cdata, id).unwrap(); - parent_def_path.data.pop(); - reader::maybe_get_doc(item_doc, item_tag::ast).map(|ast_doc| { - decode_inlined_item(cdata, tcx, parent_def_path, parent_def_id, ast_doc, item_did) - }) -} + pub fn get_super_predicates(&self, item_id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) + -> ty::GenericPredicates<'tcx> { + self.doc_predicates(self.entry(item_id), tcx, item_tag::super_predicates) + } -pub fn is_item_mir_available<'tcx>(cdata: Cmd, id: DefIndex) -> bool { - if let Some(item_doc) = cdata.get_item(id) { - return reader::maybe_get_doc(item_doc, item_tag::mir as usize).is_some(); + pub fn get_generics(&self, item_id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) + -> &'tcx ty::Generics<'tcx> { + self.doc_generics(self.entry(item_id), tcx) } - false -} + pub fn get_type(&self, id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx> { + self.doc_type(self.entry(id), tcx) + } -pub fn maybe_get_item_mir<'a, 'tcx>(cdata: Cmd, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - id: DefIndex) - -> Option> { - let item_doc = cdata.lookup_item(id); - - reader::maybe_get_doc(item_doc, item_tag::mir).map(|mir_doc| { - let mut dcx = mir_doc.decoder(); - dcx.tcx = Some(tcx); - dcx.cdata = Some(cdata); - dcx.decode() - }) -} + pub fn get_stability(&self, id: DefIndex) -> Option { + self.maybe_get(self.entry(id), item_tag::stability).map(|mut dcx| { + dcx.decode() + }) + } -pub fn get_impl_or_trait_item<'a, 'tcx>(cdata: Cmd, id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) - -> Option> { - let item_doc = cdata.lookup_item(id); - let family = item_family(item_doc); + pub fn get_deprecation(&self, id: DefIndex) -> Option { + self.maybe_get(self.entry(id), item_tag::deprecation).map(|mut dcx| { + dcx.decode() + }) + } - match family { - Family::AssociatedConst | - Family::Method | - Family::AssociatedType => {} + pub fn get_visibility(&self, id: DefIndex) -> ty::Visibility { + self.item_visibility(self.entry(id)) + } - _ => return None + fn get_impl_data(&self, id: DefIndex) -> ImplData { + match self.entry_data(self.entry(id)) { + EntryData::Impl(data) => data, + _ => bug!() + } } - let def_id = cdata.local_def_id(id); + pub fn get_parent_impl(&self, id: DefIndex) -> Option { + self.get_impl_data(id).parent_impl + } - let container_id = item_parent_item(cdata, item_doc).unwrap(); - let container = match item_family(cdata.lookup_item(container_id.index)) { - Family::Trait => TraitContainer(container_id), - _ => ImplContainer(container_id), - }; + pub fn get_impl_polarity(&self, id: DefIndex) -> hir::ImplPolarity { + self.get_impl_data(id).polarity + } - let name = item_name(item_doc); - let vis = item_visibility(item_doc); + pub fn get_custom_coerce_unsized_kind(&self, id: DefIndex) + -> Option { + self.get_impl_data(id).coerce_unsized_kind + } - let (defaultness, has_body) = match entry_data(item_doc, cdata) { - EntryData::TraitAssociated(data) => { - (hir::Defaultness::Default, data.has_default) + pub fn get_impl_trait(&self, + id: DefIndex, + tcx: TyCtxt<'a, 'tcx, 'tcx>) + -> Option> { + match self.entry_typed_data(self.entry(id), tcx) { + EntryTypedData::Impl(data) => data.trait_ref, + _ => bug!() } - EntryData::ImplAssociated(data) => { - (data.defaultness, true) - } - _ => bug!() - }; + } - Some(match family { - Family::AssociatedConst => { - let ty = doc_type(item_doc, tcx, cdata); - ty::ConstTraitItem(Rc::new(ty::AssociatedConst { - name: name, - ty: ty, - vis: vis, - defaultness: defaultness, - def_id: def_id, - container: container, - has_value: has_body, - })) + /// Iterates over the language items in the given crate. + pub fn get_lang_items(&self) -> Vec<(DefIndex, usize)> { + self.get(self.data.root(), root_tag::lang_items).decode() + } + + /// Iterates over each child of the given item. + pub fn each_child_of_item(&self, id: DefIndex, + mut get_crate_data: &mut G, + mut callback: &mut F) + where F: FnMut(Def, ast::Name, ty::Visibility), + G: FnMut(CrateNum) -> Rc, + { + // Find the item. + let item_doc = match self.maybe_entry(id) { + None => return, + Some(item_doc) => item_doc, + }; + + let dcx = match self.maybe_get(item_doc, item_tag::children) { + Some(dcx) => dcx, + None => return + }; + + // Iterate over all children. + for child_index in dcx.seq::() { + // Get the item. + if let Some(child) = self.maybe_entry(child_index) { + // Hand off the item to the callback. + let family = self.item_family(child); + if let Family::ForeignMod = family { + self.each_child_of_item(child_index, get_crate_data, callback); + } else if let Some(def) = family.to_def(self.local_def_id(child_index)) { + callback(def, self.item_name(child), self.item_visibility(child)); + } + } } - Family::Method => { - let generics = doc_generics(item_doc, tcx, cdata); - let predicates = doc_predicates(item_doc, tcx, cdata, item_tag::predicates); - let ity = tcx.lookup_item_type(def_id).ty; - let fty = match ity.sty { - ty::TyFnDef(.., fty) => fty, - _ => bug!( - "the type {:?} of the method {:?} is not a function?", - ity, name) - }; - let explicit_self = match entry_typed_data(item_doc, tcx, cdata) { - EntryTypedData::Method(data) => data.explicit_self, - _ => bug!() + let reexports = match self.entry_data(item_doc) { + EntryData::Mod(data) => data.reexports, + _ => return + }; + for exp in reexports { + // This reexport may be in yet another crate. + let crate_data = if exp.def_id.krate == self.cnum { + None + } else { + Some(get_crate_data(exp.def_id.krate)) }; - ty::MethodTraitItem(Rc::new(ty::Method { - name: name, - generics: generics, - predicates: predicates, - fty: fty, - explicit_self: explicit_self, - vis: vis, - defaultness: defaultness, - has_body: has_body, - def_id: def_id, - container: container, - })) - } - Family::AssociatedType => { - let ty = maybe_doc_type(item_doc, tcx, cdata); - ty::TypeTraitItem(Rc::new(ty::AssociatedType { - name: name, - ty: ty, - vis: vis, - defaultness: defaultness, - def_id: def_id, - container: container, - })) + let crate_data = match crate_data { + Some(ref cdata) => &**cdata, + None => self + }; + + // Get the item. + if let Some(child) = crate_data.maybe_entry(exp.def_id.index) { + // Hand off the item to the callback. + if let Some(def) = self.item_family(child).to_def(exp.def_id) { + // These items have a public visibility because they're part of + // a public re-export. + callback(def, exp.name, ty::Visibility::Public); + } + } } - _ => bug!() - }) -} + } -pub fn get_item_variances(cdata: Cmd, id: DefIndex) -> Vec { - let item_doc = cdata.lookup_item(id); - item_doc.get(item_tag::variances).decoder().decode() -} + pub fn maybe_get_item_name(&self, id: DefIndex) -> Option { + self.maybe_item_name(self.entry(id)) + } -pub fn get_struct_ctor_def_id(cdata: Cmd, node_id: DefIndex) -> Option -{ - let data = match entry_data(cdata.lookup_item(node_id), cdata) { - EntryData::Variant(data) => data, - _ => bug!() - }; + pub fn maybe_get_item_ast(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefIndex) + -> Option<&'tcx InlinedItem> { + debug!("Looking up item: {:?}", id); + let item_doc = self.entry(id); + let item_did = self.local_def_id(id); + let parent_def_id = self.local_def_id(self.def_key(id).parent.unwrap()); + let mut parent_def_path = self.def_path(id).unwrap(); + parent_def_path.data.pop(); + item_doc.maybe_child(item_tag::ast).map(|ast_doc| { + decode_inlined_item(self, tcx, parent_def_path, parent_def_id, ast_doc, item_did) + }) + } - data.struct_ctor.map(|index| cdata.local_def_id(index)) -} + pub fn is_item_mir_available(&self, id: DefIndex) -> bool { + if let Some(item_doc) = self.maybe_entry(id) { + return item_doc.maybe_child(item_tag::mir).is_some(); + } -pub fn get_item_attrs(cdata: Cmd, - node_id: DefIndex) - -> Vec { - // The attributes for a tuple struct are attached to the definition, not the ctor; - // we assume that someone passing in a tuple struct ctor is actually wanting to - // look at the definition - let mut item = cdata.lookup_item(node_id); - let def_key = item_def_key(item); - if def_key.disambiguated_data.data == DefPathData::StructCtor { - item = cdata.lookup_item(def_key.parent.unwrap()); - } - get_attributes(item) -} + false + } -pub fn get_struct_field_names(cdata: Cmd, id: DefIndex) -> Vec { - let mut dcx = cdata.lookup_item(id).get(item_tag::children).decoder(); - dcx.cdata = Some(cdata); + pub fn maybe_get_item_mir(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefIndex) + -> Option> { + self.maybe_get(self.entry(id), item_tag::mir).map(|dcx| { + dcx.typed(tcx).decode() + }) + } - dcx.seq().map(|index| item_name(cdata.lookup_item(index))).collect() -} + pub fn get_impl_or_trait_item(&self, id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) + -> Option> { + let item_doc = self.entry(id); + let family = self.item_family(item_doc); -fn get_attributes(md: rbml::Doc) -> Vec { - reader::maybe_get_doc(md, item_tag::attributes).map_or(vec![], |attrs_doc| { - let mut attrs = attrs_doc.decoder().decode::>(); + match family { + Family::AssociatedConst | + Family::Method | + Family::AssociatedType => {} - // Need new unique IDs: old thread-local IDs won't map to new threads. - for attr in attrs.iter_mut() { - attr.node.id = attr::mk_attr_id(); + _ => return None } - attrs - }) -} + let def_id = self.local_def_id(id); -#[derive(Clone)] -pub struct CrateDep { - pub cnum: CrateNum, - pub name: String, - pub hash: Svh, - pub explicitly_linked: bool, -} + let container_id = self.item_parent_item(item_doc).unwrap(); + let container = match self.item_family(self.entry(container_id.index)) { + Family::Trait => TraitContainer(container_id), + _ => ImplContainer(container_id), + }; -pub fn get_crate_deps(data: &[u8]) -> Vec { - let dcx = rbml::Doc::new(data).get(root_tag::crate_deps).decoder(); + let name = self.item_name(item_doc); + let vis = self.item_visibility(item_doc); - dcx.seq().enumerate().map(|(crate_num, (name, hash, explicitly_linked))| { - CrateDep { - cnum: CrateNum::new(crate_num + 1), - name: name, - hash: hash, - explicitly_linked: explicitly_linked, - } - }).collect() -} + let (defaultness, has_body) = match self.entry_data(item_doc) { + EntryData::TraitAssociated(data) => { + (hir::Defaultness::Default, data.has_default) + } + EntryData::ImplAssociated(data) => { + (data.defaultness, true) + } + _ => bug!() + }; -fn list_crate_deps(data: &[u8], out: &mut io::Write) -> io::Result<()> { - write!(out, "=External Dependencies=\n")?; - for dep in &get_crate_deps(data) { - write!(out, "{} {}-{}\n", dep.cnum, dep.name, dep.hash)?; + Some(match family { + Family::AssociatedConst => { + ty::ConstTraitItem(Rc::new(ty::AssociatedConst { + name: name, + ty: self.doc_type(item_doc, tcx), + vis: vis, + defaultness: defaultness, + def_id: def_id, + container: container, + has_value: has_body, + })) + } + Family::Method => { + let generics = self.doc_generics(item_doc, tcx); + let predicates = self.doc_predicates(item_doc, tcx, item_tag::predicates); + let ity = tcx.lookup_item_type(def_id).ty; + let fty = match ity.sty { + ty::TyFnDef(.., fty) => fty, + _ => bug!( + "the type {:?} of the method {:?} is not a function?", + ity, name) + }; + + let explicit_self = match self.entry_typed_data(item_doc, tcx) { + EntryTypedData::Method(data) => data.explicit_self, + _ => bug!() + }; + ty::MethodTraitItem(Rc::new(ty::Method { + name: name, + generics: generics, + predicates: predicates, + fty: fty, + explicit_self: explicit_self, + vis: vis, + defaultness: defaultness, + has_body: has_body, + def_id: def_id, + container: container, + })) + } + Family::AssociatedType => { + ty::TypeTraitItem(Rc::new(ty::AssociatedType { + name: name, + ty: self.maybe_doc_type(item_doc, tcx), + vis: vis, + defaultness: defaultness, + def_id: def_id, + container: container, + })) + } + _ => bug!() + }) } - write!(out, "\n")?; - Ok(()) -} -pub fn get_crate_info(data: &[u8]) -> CrateInfo { - rbml::Doc::new(data).get(root_tag::crate_info).decoder().decode() -} + pub fn get_item_variances(&self, id: DefIndex) -> Vec { + let item_doc = self.entry(id); + self.get(item_doc, item_tag::variances).decode() + } -pub fn list_crate_metadata(bytes: &[u8], out: &mut io::Write) -> io::Result<()> { - list_crate_deps(bytes, out) -} + pub fn get_struct_ctor_def_id(&self, node_id: DefIndex) -> Option { + let data = match self.entry_data(self.entry(node_id)) { + EntryData::Variant(data) => data, + _ => bug!() + }; -// Translate a DefId from the current compilation environment to a DefId -// for an external crate. -fn reverse_translate_def_id(cdata: Cmd, did: DefId) -> Option { - for (local, &global) in cdata.cnum_map.borrow().iter_enumerated() { - if global == did.krate { - return Some(DefId { krate: local, index: did.index }); + data.struct_ctor.map(|index| self.local_def_id(index)) + } + + pub fn get_item_attrs(&self, node_id: DefIndex) -> Vec { + // The attributes for a tuple struct are attached to the definition, not the ctor; + // we assume that someone passing in a tuple struct ctor is actually wanting to + // look at the definition + let mut item = self.entry(node_id); + let def_key = self.item_def_key(item); + if def_key.disambiguated_data.data == DefPathData::StructCtor { + item = self.entry(def_key.parent.unwrap()); } + self.get_attributes(item) } - None -} + pub fn get_struct_field_names(&self, id: DefIndex) -> Vec { + self.get(self.entry(id), item_tag::children).seq().map(|index| { + self.item_name(self.entry(index)) + }).collect() + } + + fn get_attributes(&self, md: rbml::Doc) -> Vec { + self.maybe_get(md, item_tag::attributes).map_or(vec![], |mut dcx| { + let mut attrs = dcx.decode::>(); -pub fn each_inherent_implementation_for_type(cdata: Cmd, - id: DefIndex, - mut callback: F) - where F: FnMut(DefId), -{ - let item_doc = cdata.lookup_item(id); - let mut dcx = item_doc.get(item_tag::inherent_impls).decoder(); - dcx.cdata = Some(cdata); + // Need new unique IDs: old thread-local IDs won't map to new threads. + for attr in attrs.iter_mut() { + attr.node.id = attr::mk_attr_id(); + } - for impl_def_id in dcx.seq() { - callback(impl_def_id); + attrs + }) } -} -pub fn each_implementation_for_trait(cdata: Cmd, - filter: Option, - mut callback: F) where - F: FnMut(DefId), -{ - // Do a reverse lookup beforehand to avoid touching the crate_num - // hash map in the loop below. - let filter = match filter.map(|def_id| reverse_translate_def_id(cdata, def_id)) { - Some(Some(def_id)) => Some(def_id), - Some(None) => return, - None => None - }; - - // FIXME(eddyb) Make this O(1) instead of O(n). - for trait_doc in rbml::Doc::new(cdata.data()).get(root_tag::impls).children() { - let mut dcx = trait_doc.decoder(); - dcx.cdata = Some(cdata); - - let (krate, index) = dcx.decode(); - if let Some(local_did) = filter { - if (local_did.krate.as_u32(), local_did.index) != (krate, index) { - continue; + // Translate a DefId from the current compilation environment to a DefId + // for an external crate. + fn reverse_translate_def_id(&self, did: DefId) -> Option { + for (local, &global) in self.cnum_map.borrow().iter_enumerated() { + if global == did.krate { + return Some(DefId { krate: local, index: did.index }); } } - for impl_def_id in dcx.seq() { + None + } + + pub fn each_inherent_implementation_for_type(&self, id: DefIndex, mut callback: F) + where F: FnMut(DefId), + { + for impl_def_id in self.get(self.entry(id), item_tag::inherent_impls).seq() { callback(impl_def_id); } } -} -pub fn get_trait_of_item(cdata: Cmd, id: DefIndex) -> Option { - let item_doc = cdata.lookup_item(id); - let parent_item_id = match item_parent_item(cdata, item_doc) { - None => return None, - Some(item_id) => item_id, - }; - match item_family(cdata.lookup_item(parent_item_id.index)) { - Family::Trait => Some(parent_item_id), - _ => None - } -} + pub fn each_implementation_for_trait(&self, + filter: Option, + mut callback: F) where + F: FnMut(DefId), + { + // Do a reverse lookup beforehand to avoid touching the crate_num + // hash map in the loop below. + let filter = match filter.map(|def_id| self.reverse_translate_def_id(def_id)) { + Some(Some(def_id)) => Some(def_id), + Some(None) => return, + None => None + }; + // FIXME(eddyb) Make this O(1) instead of O(n). + for trait_doc in self.data.root().children_of(root_tag::impls) { + let mut dcx = DecodeContext::new(trait_doc, Some(self)); -pub fn get_native_libraries(cdata: Cmd) - -> Vec<(cstore::NativeLibraryKind, String)> { - rbml::Doc::new(cdata.data()).get(root_tag::native_libraries).decoder().decode() -} + let (krate, index) = dcx.decode(); + if let Some(local_did) = filter { + if (local_did.krate.as_u32(), local_did.index) != (krate, index) { + continue; + } + } -pub fn each_exported_macro(data: &[u8], mut f: F) where - F: FnMut(ast::Name, Vec, Span, String) -> bool, -{ - let dcx = rbml::Doc::new(data).get(root_tag::macro_defs).decoder(); - for (name, attrs, span, body) in dcx.seq() { - if !f(name, attrs, span, body) { - break; + for impl_def_id in dcx.seq() { + callback(impl_def_id); + } } } -} -pub fn get_dylib_dependency_formats(cdata: Cmd) - -> Vec<(CrateNum, LinkagePreference)> -{ - let dcx = rbml::Doc::new(cdata.data()).get(root_tag::dylib_dependency_formats).decoder(); - - dcx.seq::>().enumerate().flat_map(|(i, link)| { - let cnum = CrateNum::new(i + 1); - link.map(|link| (cdata.cnum_map.borrow()[cnum], link)) - }).collect() -} + pub fn get_trait_of_item(&self, id: DefIndex) -> Option { + let item_doc = self.entry(id); + let parent_item_id = match self.item_parent_item(item_doc) { + None => return None, + Some(item_id) => item_id, + }; + match self.item_family(self.entry(parent_item_id.index)) { + Family::Trait => Some(parent_item_id), + _ => None + } + } -pub fn get_missing_lang_items(cdata: Cmd) -> Vec { - rbml::Doc::new(cdata.data()).get(root_tag::lang_items_missing).decoder().decode() -} -pub fn get_fn_arg_names(cdata: Cmd, id: DefIndex) -> Vec { - let method_doc = cdata.lookup_item(id); - match reader::maybe_get_doc(method_doc, item_tag::fn_arg_names) { - Some(args_doc) => args_doc.decoder().decode(), - None => vec![], + pub fn get_native_libraries(&self) -> Vec<(NativeLibraryKind, String)> { + self.get(self.data.root(), root_tag::native_libraries).decode() } -} -pub fn get_reachable_ids(cdata: Cmd) -> Vec { - let dcx = rbml::Doc::new(cdata.data()).get(root_tag::reachable_ids).decoder(); + pub fn get_dylib_dependency_formats(&self) -> Vec<(CrateNum, LinkagePreference)> { + let dcx = self.get(self.data.root(), root_tag::dylib_dependency_formats); - dcx.seq().map(|index| cdata.local_def_id(index)).collect() -} + dcx.seq::>().enumerate().flat_map(|(i, link)| { + let cnum = CrateNum::new(i + 1); + link.map(|link| (self.cnum_map.borrow()[cnum], link)) + }).collect() + } -pub fn is_const_fn(cdata: Cmd, id: DefIndex) -> bool { - let constness = match entry_data(cdata.lookup_item(id), cdata) { - EntryData::ImplAssociated(data) => data.constness, - EntryData::Fn(data) => data.constness, - _ => hir::Constness::NotConst - }; - constness == hir::Constness::Const -} + pub fn get_missing_lang_items(&self) -> Vec { + self.get(self.data.root(), root_tag::lang_items_missing).decode() + } -pub fn is_extern_item<'a, 'tcx>(cdata: Cmd, - id: DefIndex, - tcx: TyCtxt<'a, 'tcx, 'tcx>) - -> bool { - let item_doc = match cdata.get_item(id) { - Some(doc) => doc, - None => return false, - }; - let applicable = match item_family(item_doc) { - Family::ImmStatic | - Family::MutStatic | - Family::ForeignImmStatic | - Family::ForeignMutStatic => true, - - Family::Fn | Family::ForeignFn => { - get_generics(cdata, id, tcx).types.is_empty() - } + pub fn get_fn_arg_names(&self, id: DefIndex) -> Vec { + self.maybe_get(self.entry(id), item_tag::fn_arg_names) + .map_or(vec![], |mut dcx| dcx.decode()) + } - _ => false, - }; + pub fn get_reachable_ids(&self) -> Vec { + let dcx = self.get(self.data.root(), root_tag::reachable_ids); - if applicable { - attr::contains_extern_indicator(tcx.sess.diagnostic(), - &get_attributes(item_doc)) - } else { - false + dcx.seq().map(|index| self.local_def_id(index)).collect() } -} -pub fn is_foreign_item(cdata: Cmd, id: DefIndex) -> bool { - match item_family(cdata.lookup_item(id)) { - Family::ForeignImmStatic | - Family::ForeignMutStatic | - Family::ForeignFn => true, - _ => false + pub fn is_const_fn(&self, id: DefIndex) -> bool { + let constness = match self.entry_data(self.entry(id)) { + EntryData::ImplAssociated(data) => data.constness, + EntryData::Fn(data) => data.constness, + _ => hir::Constness::NotConst + }; + constness == hir::Constness::Const } -} - -fn doc_generics<'a, 'tcx>(base_doc: rbml::Doc, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - cdata: Cmd) - -> &'tcx ty::Generics<'tcx> -{ - let mut dcx = base_doc.get(item_tag::generics).decoder(); - dcx.tcx = Some(tcx); - dcx.cdata = Some(cdata); - tcx.alloc_generics(dcx.decode()) -} -fn doc_predicates<'a, 'tcx>(base_doc: rbml::Doc, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - cdata: Cmd, - tag: usize) - -> ty::GenericPredicates<'tcx> -{ - let mut dcx = base_doc.get(tag).decoder(); - dcx.cdata = Some(cdata); - dcx.tcx = Some(tcx); - - ty::GenericPredicates { - parent: dcx.decode(), - predicates: (0..dcx.decode::()).map(|_| { - // Handle shorthands first, if we have an usize > 0x80. - if dcx.opaque.data[dcx.opaque.position()] & 0x80 != 0 { - let pos = dcx.decode::(); - assert!(pos >= SHORTHAND_OFFSET); - let pos = pos - SHORTHAND_OFFSET; - - let mut dcx = rbml::Doc { - data: cdata.data(), - start: pos, - end: cdata.data().len(), - }.decoder(); - dcx.tcx = Some(tcx); - dcx.cdata = Some(cdata); - dcx.decode() - } else { - dcx.decode() + pub fn is_extern_item(&self, id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> bool { + let item_doc = match self.maybe_entry(id) { + Some(doc) => doc, + None => return false, + }; + let applicable = match self.item_family(item_doc) { + Family::ImmStatic | + Family::MutStatic | + Family::ForeignImmStatic | + Family::ForeignMutStatic => true, + + Family::Fn | Family::ForeignFn => { + self.get_generics(id, tcx).types.is_empty() } - }).collect() + + _ => false, + }; + + if applicable { + attr::contains_extern_indicator(tcx.sess.diagnostic(), + &self.get_attributes(item_doc)) + } else { + false + } } -} -pub fn is_defaulted_trait(cdata: Cmd, trait_id: DefIndex) -> bool { - match entry_data(cdata.lookup_item(trait_id), cdata) { - EntryData::Trait(data) => data.has_default_impl, - _ => bug!() + pub fn is_foreign_item(&self, id: DefIndex) -> bool { + match self.item_family(self.entry(id)) { + Family::ForeignImmStatic | + Family::ForeignMutStatic | + Family::ForeignFn => true, + _ => false + } } -} -pub fn is_default_impl(cdata: Cmd, impl_id: DefIndex) -> bool { - item_family(cdata.lookup_item(impl_id)) == Family::DefaultImpl -} + fn doc_generics(&self, base_doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>) + -> &'tcx ty::Generics<'tcx> { + let generics = self.get(base_doc, item_tag::generics).typed(tcx).decode(); + tcx.alloc_generics(generics) + } -pub fn get_imported_filemaps(metadata: &[u8]) -> Vec { - rbml::Doc::new(metadata).get(root_tag::codemap).decoder().decode() -} + fn doc_predicates(&self, base_doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>, tag: usize) + -> ty::GenericPredicates<'tcx> { + let mut dcx = self.get(base_doc, tag).typed(tcx); + + ty::GenericPredicates { + parent: dcx.decode(), + predicates: (0..dcx.decode::()).map(|_| { + // Handle shorthands first, if we have an usize > 0x80. + if dcx.opaque.data[dcx.opaque.position()] & 0x80 != 0 { + let pos = dcx.decode::(); + assert!(pos >= SHORTHAND_OFFSET); + let pos = pos - SHORTHAND_OFFSET; + + let data = self.data.as_slice(); + let doc = rbml::Doc { + data: data, + start: pos, + end: data.len(), + }; + DecodeContext::new(doc, Some(self)).typed(tcx).decode() + } else { + dcx.decode() + } + }).collect() + } + } -pub fn closure_kind(cdata: Cmd, closure_id: DefIndex) -> ty::ClosureKind { - match entry_data(cdata.lookup_item(closure_id), cdata) { - EntryData::Closure(data) => data.kind, - _ => bug!() + pub fn is_defaulted_trait(&self, trait_id: DefIndex) -> bool { + match self.entry_data(self.entry(trait_id)) { + EntryData::Trait(data) => data.has_default_impl, + _ => bug!() + } } -} -pub fn closure_ty<'a, 'tcx>(cdata: Cmd, closure_id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) - -> ty::ClosureTy<'tcx> { - match entry_typed_data(cdata.lookup_item(closure_id), tcx, cdata) { - EntryTypedData::Closure(data) => data.ty, - _ => bug!() + pub fn is_default_impl(&self, impl_id: DefIndex) -> bool { + self.item_family(self.entry(impl_id)) == Family::DefaultImpl } -} -pub fn def_key(cdata: Cmd, id: DefIndex) -> hir_map::DefKey { - debug!("def_key: id={:?}", id); - item_def_key(cdata.lookup_item(id)) -} + pub fn closure_kind(&self, closure_id: DefIndex) -> ty::ClosureKind { + match self.entry_data(self.entry(closure_id)) { + EntryData::Closure(data) => data.kind, + _ => bug!() + } + } -fn item_def_key(item_doc: rbml::Doc) -> hir_map::DefKey { - item_doc.get(item_tag::def_key).decoder().decode() -} + pub fn closure_ty(&self, closure_id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) + -> ty::ClosureTy<'tcx> { + match self.entry_typed_data(self.entry(closure_id), tcx) { + EntryTypedData::Closure(data) => data.ty, + _ => bug!() + } + } -// Returns the path leading to the thing with this `id`. Note that -// some def-ids don't wind up in the metadata, so `def_path` sometimes -// returns `None` -pub fn def_path(cdata: Cmd, id: DefIndex) -> Option { - debug!("def_path(id={:?})", id); - if cdata.get_item(id).is_some() { - Some(hir_map::DefPath::make(cdata.cnum, id, |parent| def_key(cdata, parent))) - } else { - None + pub fn def_key(&self, id: DefIndex) -> hir_map::DefKey { + debug!("def_key: id={:?}", id); + self.item_def_key(self.entry(id)) + } + + // Returns the path leading to the thing with this `id`. Note that + // some def-ids don't wind up in the metadata, so `def_path` sometimes + // returns `None` + pub fn def_path(&self, id: DefIndex) -> Option { + debug!("def_path(id={:?})", id); + if self.maybe_entry(id).is_some() { + Some(hir_map::DefPath::make(self.cnum, id, |parent| self.def_key(parent))) + } else { + None + } } } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 637228725e0be..e345129b327e9 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -11,7 +11,6 @@ // Metadata encoding #![allow(unused_must_use)] // everything is just a MemWriter, can't fail -#![allow(non_camel_case_types)] use astencode::encode_inlined_item; use common::*; @@ -226,9 +225,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { struct_ctor: struct_ctor }) } -} -impl<'a, 'tcx> EncodeContext<'a, 'tcx> { /// Encode data for the given variant of the given ADT. The /// index of the variant is untracked: this is ok because we /// will have to lookup the adt-def by its id, and that gives us @@ -249,8 +246,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.encode_visibility(enum_vis); let attrs = tcx.get_attrs(vid); - encode_attributes(self, &attrs); - encode_stability(self, vid); + self.encode_attributes(&attrs); + self.encode_stability(vid); let data = self.encode_variant(variant, None); @@ -264,9 +261,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.encode_bounds_and_type_for_item(vid); } -} -impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn encode_info_for_mod(&mut self, FromId(id, (md, attrs, vis)): FromId<(&hir::Mod, &[ast::Attribute], &hir::Visibility)>) { @@ -276,8 +271,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.encode_def_key(def_id); self.encode_family(Family::Mod); self.encode_visibility(vis); - encode_stability(self, def_id); - encode_attributes(self, attrs); + self.encode_stability(def_id); + self.encode_attributes(attrs); debug!("(encoding info for module) encoding info for module ID {}", id); // Encode info about all the module children. @@ -371,8 +366,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let variant_id = tcx.map.as_local_node_id(variant.did).unwrap(); let variant_data = tcx.map.expect_variant_data(variant_id); - encode_attributes(self, &variant_data.fields()[field_index].attrs); - encode_stability(self, field.did); + self.encode_attributes(&variant_data.fields()[field_index].attrs); + self.encode_stability(field.did); } fn encode_struct_ctor(&mut self, ctor_def_id: DefId) { @@ -380,7 +375,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.encode_family(Family::Struct); self.encode_bounds_and_type_for_item(ctor_def_id); - encode_stability(self, ctor_def_id); + self.encode_stability(ctor_def_id); } fn encode_generics(&mut self, @@ -445,8 +440,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.encode_family(family); self.encode_visibility(trait_item.vis()); - encode_stability(self, def_id); - encode_attributes(self, &ast_item.attrs); + self.encode_stability(def_id); + self.encode_attributes(&ast_item.attrs); if let hir::MethodTraitItem(ref sig, _) = ast_item.node { self.encode_fn_arg_names(&sig.decl); }; @@ -499,8 +494,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.encode_def_key(def_id); self.encode_family(family); self.encode_visibility(impl_item.vis()); - encode_attributes(self, &ast_item.attrs); - encode_stability(self, def_id); + self.encode_attributes(&ast_item.attrs); + self.encode_stability(def_id); let constness = if let hir::ImplItemKind::Method(ref sig, _) = ast_item.node { if sig.constness == hir::Constness::Const { @@ -555,33 +550,30 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.end_tag(); } } -} -// Encodes the inherent implementations of a structure, enumeration, or trait. -fn encode_inherent_implementations(ecx: &mut EncodeContext, - def_id: DefId) { - ecx.start_tag(item_tag::inherent_impls); - match ecx.tcx.inherent_impls.borrow().get(&def_id) { - None => <[DefId]>::encode(&[], ecx).unwrap(), - Some(implementations) => implementations.encode(ecx).unwrap() + // Encodes the inherent implementations of a structure, enumeration, or trait. + fn encode_inherent_implementations(&mut self, def_id: DefId) { + self.start_tag(item_tag::inherent_impls); + match self.tcx.inherent_impls.borrow().get(&def_id) { + None => <[DefId]>::encode(&[], self).unwrap(), + Some(implementations) => implementations.encode(self).unwrap() + } + self.end_tag(); } - ecx.end_tag(); -} -fn encode_stability(ecx: &mut EncodeContext, def_id: DefId) { - ecx.tcx.lookup_stability(def_id).map(|stab| { - ecx.start_tag(item_tag::stability); - stab.encode(ecx).unwrap(); - ecx.end_tag(); - }); - ecx.tcx.lookup_deprecation(def_id).map(|depr| { - ecx.start_tag(item_tag::deprecation); - depr.encode(ecx).unwrap(); - ecx.end_tag(); - }); -} + fn encode_stability(&mut self, def_id: DefId) { + self.tcx.lookup_stability(def_id).map(|stab| { + self.start_tag(item_tag::stability); + stab.encode(self).unwrap(); + self.end_tag(); + }); + self.tcx.lookup_deprecation(def_id).map(|depr| { + self.start_tag(item_tag::deprecation); + depr.encode(self).unwrap(); + self.end_tag(); + }); + } -impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn encode_info_for_item(&mut self, (def_id, item): (DefId, &hir::Item)) { let tcx = self.tcx; @@ -652,7 +644,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.end_tag(); // Encode inherent implementations for self enumeration. - encode_inherent_implementations(self, def_id); + self.encode_inherent_implementations(def_id); (Family::Enum, EntryData::Other, EntryTypedData::Other) } @@ -675,7 +667,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let data = self.encode_variant(variant, struct_ctor); // Encode inherent implementations for self structure. - encode_inherent_implementations(self, def_id); + self.encode_inherent_implementations(def_id); (Family::Struct, data, EntryTypedData::Other) } @@ -691,7 +683,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let data = self.encode_variant(def.struct_variant(), None); // Encode inherent implementations for self union. - encode_inherent_implementations(self, def_id); + self.encode_inherent_implementations(def_id); (Family::Union, data, EntryTypedData::Other) } @@ -752,7 +744,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.end_tag(); // Encode inherent implementations for self trait. - encode_inherent_implementations(self, def_id); + self.encode_inherent_implementations(def_id); (Family::Trait, EntryData::Trait(TraitData { @@ -772,8 +764,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.encode_family(family); self.encode_def_key(def_id); self.encode_visibility(&item.vis); - encode_attributes(self, &item.attrs); - encode_stability(self, def_id); + self.encode_attributes(&item.attrs); + self.encode_stability(def_id); self.start_tag(item_tag::data); data.encode(self).unwrap(); @@ -883,8 +875,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { EntryTypedData::Other.encode(self).unwrap(); self.end_tag(); - encode_attributes(self, &nitem.attrs); - encode_stability(self, def_id); + self.encode_attributes(&nitem.attrs); + self.encode_stability(def_id); } } @@ -970,152 +962,153 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { assert!(self.mir_map.map.contains_key(&def_id)); self.encode_mir(def_id); } -} -fn encode_info_for_items(ecx: &mut EncodeContext) -> IndexData { - let krate = ecx.tcx.map.krate(); - - // FIXME(eddyb) Avoid wrapping the items in a doc. - ecx.start_tag(0).unwrap(); - - let items = { - let mut index = IndexBuilder::new(ecx); - index.record(DefId::local(CRATE_DEF_INDEX), - EncodeContext::encode_info_for_mod, - FromId(CRATE_NODE_ID, (&krate.module, &krate.attrs, &hir::Public))); - let mut visitor = EncodeVisitor { - index: index, + fn encode_info_for_items(&mut self) -> IndexData { + let krate = self.tcx.map.krate(); + + // FIXME(eddyb) Avoid wrapping the items in a doc. + self.start_tag(0).unwrap(); + + let items = { + let mut index = IndexBuilder::new(self); + index.record(DefId::local(CRATE_DEF_INDEX), + EncodeContext::encode_info_for_mod, + FromId(CRATE_NODE_ID, (&krate.module, &krate.attrs, &hir::Public))); + let mut visitor = EncodeVisitor { + index: index, + }; + krate.visit_all_items(&mut visitor); + visitor.index.into_items() }; - krate.visit_all_items(&mut visitor); - visitor.index.into_items() - }; - ecx.end_tag(); + self.end_tag(); - items -} + items + } -fn encode_item_index(ecx: &mut EncodeContext, index: IndexData) { - ecx.start_tag(root_tag::index); - index.write_index(&mut ecx.opaque.cursor); - ecx.end_tag(); -} + fn encode_item_index(&mut self, index: IndexData) { + self.start_tag(root_tag::index); + index.write_index(&mut self.opaque.cursor); + self.end_tag(); + } -fn encode_attributes(ecx: &mut EncodeContext, attrs: &[ast::Attribute]) { - ecx.start_tag(item_tag::attributes); - attrs.encode(ecx).unwrap(); - ecx.end_tag(); -} + fn encode_attributes(&mut self, attrs: &[ast::Attribute]) { + self.start_tag(item_tag::attributes); + attrs.encode(self).unwrap(); + self.end_tag(); + } -fn encode_crate_deps(ecx: &mut EncodeContext, cstore: &cstore::CStore) { - fn get_ordered_deps(cstore: &cstore::CStore) - -> Vec<(CrateNum, Rc)> { - // Pull the cnums and name,vers,hash out of cstore - let mut deps = Vec::new(); - cstore.iter_crate_data(|cnum, val| { - deps.push((cnum, val.clone())); - }); + fn encode_crate_deps(&mut self) { + fn get_ordered_deps(cstore: &cstore::CStore) + -> Vec<(CrateNum, Rc)> { + // Pull the cnums and name,vers,hash out of cstore + let mut deps = Vec::new(); + cstore.iter_crate_data(|cnum, val| { + deps.push((cnum, val.clone())); + }); - // Sort by cnum - deps.sort_by(|kv1, kv2| kv1.0.cmp(&kv2.0)); + // Sort by cnum + deps.sort_by(|kv1, kv2| kv1.0.cmp(&kv2.0)); - // Sanity-check the crate numbers - let mut expected_cnum = 1; - for &(n, _) in &deps { - assert_eq!(n, CrateNum::new(expected_cnum)); - expected_cnum += 1; + // Sanity-check the crate numbers + let mut expected_cnum = 1; + for &(n, _) in &deps { + assert_eq!(n, CrateNum::new(expected_cnum)); + expected_cnum += 1; + } + + deps } - deps + // We're just going to write a list of crate 'name-hash-version's, with + // the assumption that they are numbered 1 to n. + // FIXME (#2166): This is not nearly enough to support correct versioning + // but is enough to get transitive crate dependencies working. + self.start_tag(root_tag::crate_deps); + let deps = get_ordered_deps(self.cstore); + self.seq(&deps, |_, &(_, ref dep)| { + (dep.name(), dep.hash(), dep.explicitly_linked.get()) + }); + self.end_tag(); } - // We're just going to write a list of crate 'name-hash-version's, with - // the assumption that they are numbered 1 to n. - // FIXME (#2166): This is not nearly enough to support correct versioning - // but is enough to get transitive crate dependencies working. - ecx.start_tag(root_tag::crate_deps); - ecx.seq(&get_ordered_deps(cstore), |_, &(_, ref dep)| { - (dep.name(), dep.hash(), dep.explicitly_linked.get()) - }); - ecx.end_tag(); -} - -fn encode_lang_items(ecx: &mut EncodeContext) { - let tcx = ecx.tcx; - let lang_items = || { - tcx.lang_items.items().iter().enumerate().filter_map(|(i, &opt_def_id)| { - if let Some(def_id) = opt_def_id { - if def_id.is_local() { - return Some((def_id.index, i)); + fn encode_lang_items(&mut self) { + let tcx = self.tcx; + let lang_items = || { + tcx.lang_items.items().iter().enumerate().filter_map(|(i, &opt_def_id)| { + if let Some(def_id) = opt_def_id { + if def_id.is_local() { + return Some((def_id.index, i)); + } } - } - None - }) - }; + None + }) + }; - let count = lang_items().count(); - let mut lang_items = lang_items(); + let count = lang_items().count(); + let mut lang_items = lang_items(); - ecx.start_tag(root_tag::lang_items); - ecx.seq(0..count, |_, _| lang_items.next().unwrap()); - ecx.end_tag(); + self.start_tag(root_tag::lang_items); + self.seq(0..count, |_, _| lang_items.next().unwrap()); + self.end_tag(); - ecx.start_tag(root_tag::lang_items_missing); - tcx.lang_items.missing.encode(ecx).unwrap(); - ecx.end_tag(); -} + self.start_tag(root_tag::lang_items_missing); + tcx.lang_items.missing.encode(self).unwrap(); + self.end_tag(); + } -fn encode_native_libraries(ecx: &mut EncodeContext) { - let used_libraries = ecx.tcx.sess.cstore.used_libraries(); - let libs = || { - used_libraries.iter().filter_map(|&(ref lib, kind)| { - match kind { - cstore::NativeStatic => None, // these libraries are not propagated - cstore::NativeFramework | cstore::NativeUnknown => { - Some((kind, lib)) + fn encode_native_libraries(&mut self) { + let used_libraries = self.tcx.sess.cstore.used_libraries(); + let libs = || { + used_libraries.iter().filter_map(|&(ref lib, kind)| { + match kind { + cstore::NativeStatic => None, // these libraries are not propagated + cstore::NativeFramework | cstore::NativeUnknown => { + Some((kind, lib)) + } } - } - }) - }; + }) + }; - let count = libs().count(); - let mut libs = libs(); + let count = libs().count(); + let mut libs = libs(); - ecx.start_tag(root_tag::native_libraries); - ecx.seq(0..count, |_, _| libs.next().unwrap()); - ecx.end_tag(); -} + self.start_tag(root_tag::native_libraries); + self.seq(0..count, |_, _| libs.next().unwrap()); + self.end_tag(); + } -fn encode_codemap(ecx: &mut EncodeContext) { - let codemap = ecx.tcx.sess.codemap(); - let all_filemaps = codemap.files.borrow(); - let filemaps = || { - // No need to export empty filemaps, as they can't contain spans - // that need translation. - // Also no need to re-export imported filemaps, as any downstream - // crate will import them from their original source. - all_filemaps.iter().filter(|filemap| { - !filemap.lines.borrow().is_empty() && !filemap.is_imported() - }) - }; + fn encode_codemap(&mut self) { + let codemap = self.tcx.sess.codemap(); + let all_filemaps = codemap.files.borrow(); + let filemaps = || { + // No need to export empty filemaps, as they can't contain spans + // that need translation. + // Also no need to re-export imported filemaps, as any downstream + // crate will import them from their original source. + all_filemaps.iter().filter(|filemap| { + !filemap.lines.borrow().is_empty() && !filemap.is_imported() + }) + }; - let count = filemaps().count(); - let mut filemaps = filemaps(); + let count = filemaps().count(); + let mut filemaps = filemaps(); - ecx.start_tag(root_tag::codemap); - ecx.seq(0..count, |_, _| filemaps.next().unwrap()); - ecx.end_tag(); -} + self.start_tag(root_tag::codemap); + self.seq(0..count, |_, _| filemaps.next().unwrap()); + self.end_tag(); + } -/// Serialize the text of the exported macros -fn encode_macro_defs(ecx: &mut EncodeContext) { - let tcx = ecx.tcx; - ecx.start_tag(root_tag::macro_defs); - ecx.seq(&tcx.map.krate().exported_macros, |_, def| { - let body = ::syntax::print::pprust::tts_to_string(&def.body); - (def.name, &def.attrs, def.span, body) - }); - ecx.end_tag(); + /// Serialize the text of the exported macros + fn encode_macro_defs(&mut self) { + let tcx = self.tcx; + self.start_tag(root_tag::macro_defs); + self.seq(&tcx.map.krate().exported_macros, |_, def| { + let body = ::syntax::print::pprust::tts_to_string(&def.body); + (def.name, &def.attrs, def.span, body) + }); + self.end_tag(); + } } struct ImplVisitor<'a, 'tcx:'a> { @@ -1136,59 +1129,61 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ImplVisitor<'a, 'tcx> { } } -/// Encodes an index, mapping each trait to its (local) implementations. -fn encode_impls(ecx: &mut EncodeContext) { - let mut visitor = ImplVisitor { - tcx: ecx.tcx, - impls: FnvHashMap() - }; - ecx.tcx.map.krate().visit_all_items(&mut visitor); - - ecx.start_tag(root_tag::impls); - for (trait_def_id, trait_impls) in visitor.impls { - // FIXME(eddyb) Avoid wrapping the entries in docs. - ecx.start_tag(0); - (trait_def_id.krate.as_u32(), trait_def_id.index).encode(ecx).unwrap(); - trait_impls.encode(ecx).unwrap(); - ecx.end_tag(); +impl<'a, 'tcx> EncodeContext<'a, 'tcx> { + /// Encodes an index, mapping each trait to its (local) implementations. + fn encode_impls(&mut self) { + let mut visitor = ImplVisitor { + tcx: self.tcx, + impls: FnvHashMap() + }; + self.tcx.map.krate().visit_all_items(&mut visitor); + + self.start_tag(root_tag::impls); + for (trait_def_id, trait_impls) in visitor.impls { + // FIXME(eddyb) Avoid wrapping the entries in docs. + self.start_tag(0); + (trait_def_id.krate.as_u32(), trait_def_id.index).encode(self).unwrap(); + trait_impls.encode(self).unwrap(); + self.end_tag(); + } + self.end_tag(); } - ecx.end_tag(); -} -// Encodes all reachable symbols in this crate into the metadata. -// -// This pass is seeded off the reachability list calculated in the -// middle::reachable module but filters out items that either don't have a -// symbol associated with them (they weren't translated) or if they're an FFI -// definition (as that's not defined in this crate). -fn encode_reachable(ecx: &mut EncodeContext) { - ecx.start_tag(root_tag::reachable_ids); + // Encodes all reachable symbols in this crate into the metadata. + // + // This pass is seeded off the reachability list calculated in the + // middle::reachable module but filters out items that either don't have a + // symbol associated with them (they weren't translated) or if they're an FFI + // definition (as that's not defined in this crate). + fn encode_reachable(&mut self) { + self.start_tag(root_tag::reachable_ids); - let reachable = ecx.reachable; - ecx.seq(reachable, |ecx, &id| ecx.tcx.map.local_def_id(id).index); + let reachable = self.reachable; + self.seq(reachable, |ecx, &id| ecx.tcx.map.local_def_id(id).index); - ecx.end_tag(); -} + self.end_tag(); + } -fn encode_dylib_dependency_formats(ecx: &mut EncodeContext) { - ecx.start_tag(root_tag::dylib_dependency_formats); - match ecx.tcx.sess.dependency_formats.borrow().get(&config::CrateTypeDylib) { - Some(arr) => { - ecx.seq(arr, |_, slot| { - match *slot { - Linkage::NotLinked | - Linkage::IncludedFromDylib => None, - - Linkage::Dynamic => Some(LinkagePreference::RequireDynamic), - Linkage::Static => Some(LinkagePreference::RequireStatic), - } - }); - } - None => { - <[Option]>::encode(&[], ecx).unwrap(); + fn encode_dylib_dependency_formats(&mut self) { + self.start_tag(root_tag::dylib_dependency_formats); + match self.tcx.sess.dependency_formats.borrow().get(&config::CrateTypeDylib) { + Some(arr) => { + self.seq(arr, |_, slot| { + match *slot { + Linkage::NotLinked | + Linkage::IncludedFromDylib => None, + + Linkage::Dynamic => Some(LinkagePreference::RequireDynamic), + Linkage::Static => Some(LinkagePreference::RequireStatic), + } + }); + } + None => { + <[Option]>::encode(&[], self).unwrap(); + } } + self.end_tag(); } - ecx.end_tag(); } pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -1281,47 +1276,47 @@ fn encode_metadata_inner(ecx: &mut EncodeContext) { ecx.end_tag(); let mut i = ecx.position(); - encode_crate_deps(ecx, ecx.cstore); - encode_dylib_dependency_formats(ecx); + ecx.encode_crate_deps(); + ecx.encode_dylib_dependency_formats(); let dep_bytes = ecx.position() - i; // Encode the language items. i = ecx.position(); - encode_lang_items(ecx); + ecx.encode_lang_items(); let lang_item_bytes = ecx.position() - i; // Encode the native libraries used i = ecx.position(); - encode_native_libraries(ecx); + ecx.encode_native_libraries(); let native_lib_bytes = ecx.position() - i; // Encode codemap i = ecx.position(); - encode_codemap(ecx); + ecx.encode_codemap(); let codemap_bytes = ecx.position() - i; // Encode macro definitions i = ecx.position(); - encode_macro_defs(ecx); + ecx.encode_macro_defs(); let macro_defs_bytes = ecx.position() - i; // Encode the def IDs of impls, for coherence checking. i = ecx.position(); - encode_impls(ecx); + ecx.encode_impls(); let impl_bytes = ecx.position() - i; // Encode reachability info. i = ecx.position(); - encode_reachable(ecx); + ecx.encode_reachable(); let reachable_bytes = ecx.position() - i; // Encode and index the items. i = ecx.position(); - let items = encode_info_for_items(ecx); + let items = ecx.encode_info_for_items(); let item_bytes = ecx.position() - i; i = ecx.position(); - encode_item_index(ecx, items); + ecx.encode_item_index(items); let index_bytes = ecx.position() - i; let total_bytes = ecx.position(); diff --git a/src/librustc_metadata/loader.rs b/src/librustc_metadata/loader.rs index 47bf65bead9af..883004b8486f1 100644 --- a/src/librustc_metadata/loader.rs +++ b/src/librustc_metadata/loader.rs @@ -214,7 +214,6 @@ use cstore::{MetadataBlob, MetadataVec, MetadataArchive}; use common::{metadata_encoding_version, rustc_version}; -use decoder; use rustc::hir::svh::Svh; use rustc::session::Session; @@ -511,7 +510,7 @@ impl<'a> Context<'a> { if let Some((ref p, _)) = lib.rlib { err.note(&format!("path: {}", p.display())); } - let crate_info = decoder::get_crate_info(lib.metadata.as_slice()); + let crate_info = lib.metadata.get_crate_info(); note_crate_name(&mut err, &crate_info.name); } err.emit(); @@ -550,7 +549,7 @@ impl<'a> Context<'a> { info!("{} reading metadata from: {}", flavor, lib.display()); let (hash, metadata) = match get_metadata_section(self.target, flavor, &lib) { Ok(blob) => { - if let Some(h) = self.crate_matches(blob.as_slice(), &lib) { + if let Some(h) = self.crate_matches(&blob, &lib) { (h, blob) } else { info!("metadata mismatch"); @@ -597,8 +596,8 @@ impl<'a> Context<'a> { } } - fn crate_matches(&mut self, crate_data: &[u8], libpath: &Path) -> Option { - let crate_rustc_version = decoder::crate_rustc_version(crate_data); + fn crate_matches(&mut self, metadata: &MetadataBlob, libpath: &Path) -> Option { + let crate_rustc_version = metadata.crate_rustc_version(); if crate_rustc_version != Some(rustc_version()) { let message = crate_rustc_version.unwrap_or(format!("an unknown compiler")); info!("Rejecting via version: expected {} got {}", rustc_version(), message); @@ -609,7 +608,7 @@ impl<'a> Context<'a> { return None; } - let crate_info = decoder::get_crate_info(crate_data); + let crate_info = metadata.get_crate_info(); if self.should_match_name { if self.crate_name != crate_info.name { info!("Rejecting via crate name"); return None; @@ -895,7 +894,7 @@ pub fn list_file_metadata(target: &Target, path: &Path, let filename = path.file_name().unwrap().to_str().unwrap(); let flavor = if filename.ends_with(".rlib") { CrateFlavor::Rlib } else { CrateFlavor::Dylib }; match get_metadata_section(target, flavor, path) { - Ok(bytes) => decoder::list_crate_metadata(bytes.as_slice(), out), + Ok(metadata) => metadata.list_crate_metadata(out), Err(msg) => { write!(out, "{}\n", msg) } diff --git a/src/librustc_metadata/rbml/reader.rs b/src/librustc_metadata/rbml/reader.rs index 24a0329602beb..c4cfc32d63306 100644 --- a/src/librustc_metadata/rbml/reader.rs +++ b/src/librustc_metadata/rbml/reader.rs @@ -52,6 +52,15 @@ use test::Bencher; use std::fmt; use std::str; +macro_rules! try_or { + ($e:expr, $r:expr) => ( + match $e { + Ok(x) => x, + Err(_) => return $r + } + ) +} + #[derive(Clone, Copy)] pub struct Doc<'a> { pub data: &'a [u8], @@ -79,17 +88,34 @@ impl<'doc> Doc<'doc> { } } - pub fn get(&self, tag: usize) -> Doc<'doc> { - match maybe_get_doc(*self, tag) { + pub fn maybe_child(&self, tag: usize) -> Option> { + let mut pos = self.start; + while pos < self.end { + let elt_tag = try_or!(tag_at(self.data, pos), None); + let elt_size = try_or!(tag_len_at(self.data, elt_tag.next), None); + pos = elt_size.next + elt_size.val; + if elt_tag.val == tag { + return Some(Doc { + data: self.data, + start: elt_size.next, + end: pos, + }); + } + } + None + } + + pub fn child(&self, tag: usize) -> Doc<'doc> { + match self.maybe_child(tag) { Some(d) => d, None => { - bug!("failed to find block with tag {:?}", tag); + bug!("failed to find child with tag {:?}", tag); } } } - pub fn children(self) -> DocsIterator<'doc> { - DocsIterator { d: self } + pub fn children_of(&self, tag: usize) -> DocsIterator<'doc> { + DocsIterator { d: self.child(tag) } } } @@ -106,24 +132,10 @@ impl fmt::Display for Error { } } -// rbml reading - -macro_rules! try_or { - ($e:expr, $r:expr) => ( - match $e { - Ok(e) => e, - Err(e) => { - debug!("ignored error: {:?}", e); - return $r - } - } - ) -} - #[derive(Copy, Clone)] -pub struct Res { - pub val: usize, - pub next: usize, +struct Res { + val: usize, + next: usize, } fn tag_at(data: &[u8], start: usize) -> Result { @@ -235,23 +247,6 @@ fn tag_len_at(data: &[u8], next: usize) -> Result { vuint_at(data, next) } -pub fn maybe_get_doc<'a>(d: Doc<'a>, tg: usize) -> Option> { - let mut pos = d.start; - while pos < d.end { - let elt_tag = try_or!(tag_at(d.data, pos), None); - let elt_size = try_or!(tag_len_at(d.data, elt_tag.next), None); - pos = elt_size.next + elt_size.val; - if elt_tag.val == tg { - return Some(Doc { - data: d.data, - start: elt_size.next, - end: pos, - }); - } - } - None -} - pub struct DocsIterator<'a> { d: Doc<'a>, } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 43a9b4e49e393..0acf211a27c53 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -237,8 +237,8 @@ pub struct ExternalCrate { impl Clean for CrateNum { fn clean(&self, cx: &DocContext) -> ExternalCrate { let mut primitives = Vec::new(); + let root = DefId { krate: self.0, index: CRATE_DEF_INDEX }; cx.tcx_opt().map(|tcx| { - let root = DefId { krate: self.0, index: CRATE_DEF_INDEX }; for item in tcx.sess.cstore.item_children(root) { let did = match item.def { Def::Mod(did) => did, @@ -250,7 +250,7 @@ impl Clean for CrateNum { }); ExternalCrate { name: (&cx.sess().cstore.crate_name(self.0)[..]).to_owned(), - attrs: cx.sess().cstore.crate_attrs(self.0).clean(cx), + attrs: cx.sess().cstore.item_attrs(root).clean(cx), primitives: primitives, } } From 24aef24e1aa732115c1a98feb06510de372fcf0c Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Thu, 15 Sep 2016 11:05:45 +0300 Subject: [PATCH 27/39] rustc_metadata: split the Def description of a DefId from item_children. --- src/librustc/middle/cstore.rs | 13 ++--- src/librustc_metadata/csearch.rs | 36 +++++------- src/librustc_metadata/decoder.rs | 62 ++++++++++----------- src/librustc_metadata/encoder.rs | 1 + src/librustc_resolve/build_reduced_graph.rs | 25 ++++++--- src/librustc_typeck/check/method/suggest.rs | 20 +++---- src/librustdoc/clean/inline.rs | 10 ++-- src/librustdoc/clean/mod.rs | 6 +- src/librustdoc/visit_lib.rs | 31 ++++------- 9 files changed, 95 insertions(+), 109 deletions(-) diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 6324995f328b9..dbbd5eca4832e 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -96,13 +96,6 @@ pub enum InlinedItemRef<'a> { ImplItem(DefId, &'a hir::ImplItem) } -#[derive(Copy, Clone)] -pub struct ChildItem { - pub def: Def, - pub name: ast::Name, - pub vis: ty::Visibility, -} - #[derive(Copy, Clone, Debug)] pub struct ExternCrate { /// def_id of an `extern crate` in the current crate that caused @@ -128,6 +121,7 @@ pub struct ExternCrate { /// can be accessed. pub trait CrateStore<'tcx> { // item info + fn describe_def(&self, def: DefId) -> Option; fn stability(&self, def: DefId) -> Option; fn deprecation(&self, def: DefId) -> Option; fn visibility(&self, def: DefId) -> ty::Visibility; @@ -209,7 +203,7 @@ pub trait CrateStore<'tcx> { fn relative_def_path(&self, def: DefId) -> Option; fn struct_ctor_def_id(&self, struct_def_id: DefId) -> Option; fn struct_field_names(&self, def: DefId) -> Vec; - fn item_children(&self, did: DefId) -> Vec; + fn item_children(&self, did: DefId) -> Vec; // misc. metadata fn maybe_get_item_ast<'a>(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) @@ -286,6 +280,7 @@ pub struct DummyCrateStore; #[allow(unused_variables)] impl<'tcx> CrateStore<'tcx> for DummyCrateStore { // item info + fn describe_def(&self, def: DefId) -> Option { bug!("describe_def") } fn stability(&self, def: DefId) -> Option { bug!("stability") } fn deprecation(&self, def: DefId) -> Option { bug!("deprecation") } fn visibility(&self, def: DefId) -> ty::Visibility { bug!("visibility") } @@ -386,7 +381,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { fn struct_ctor_def_id(&self, struct_def_id: DefId) -> Option { bug!("struct_ctor_def_id") } fn struct_field_names(&self, def: DefId) -> Vec { bug!("struct_field_names") } - fn item_children(&self, did: DefId) -> Vec { bug!("item_children") } + fn item_children(&self, did: DefId) -> Vec { bug!("item_children") } // misc. metadata fn maybe_get_item_ast<'a>(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) diff --git a/src/librustc_metadata/csearch.rs b/src/librustc_metadata/csearch.rs index 8136fc7e845f3..8569dbcd50733 100644 --- a/src/librustc_metadata/csearch.rs +++ b/src/librustc_metadata/csearch.rs @@ -13,9 +13,9 @@ use common; use encoder; use loader; -use rustc::middle::cstore::{InlinedItem, CrateStore, CrateSource, ChildItem, ExternCrate}; +use rustc::middle::cstore::{InlinedItem, CrateStore, CrateSource, ExternCrate}; use rustc::middle::cstore::{NativeLibraryKind, LinkMeta, LinkagePreference}; -use rustc::hir::def; +use rustc::hir::def::{self, Def}; use rustc::middle::lang_items; use rustc::ty::{self, Ty, TyCtxt}; use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX}; @@ -37,6 +37,11 @@ use rustc_back::target::Target; use rustc::hir; impl<'tcx> CrateStore<'tcx> for cstore::CStore { + fn describe_def(&self, def: DefId) -> Option { + self.dep_graph.read(DepNode::MetaData(def)); + self.get_crate_data(def.krate).get_def(def.index) + } + fn stability(&self, def: DefId) -> Option { self.dep_graph.read(DepNode::MetaData(def)); self.get_crate_data(def.krate).get_stability(def.index) @@ -158,10 +163,8 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { fn impl_or_trait_items(&self, def_id: DefId) -> Vec { self.dep_graph.read(DepNode::MetaData(def_id)); let mut result = vec![]; - let get_crate_data = &mut |cnum| self.get_crate_data(cnum); self.get_crate_data(def_id.krate) - .each_child_of_item(def_id.index, get_crate_data, - &mut |def, _, _| result.push(def.def_id())); + .each_child_of_item(def_id.index, |child| result.push(child.def_id)); result } @@ -366,20 +369,12 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { self.get_crate_data(def.krate).get_struct_field_names(def.index) } - fn item_children(&self, def_id: DefId) -> Vec + fn item_children(&self, def_id: DefId) -> Vec { self.dep_graph.read(DepNode::MetaData(def_id)); let mut result = vec![]; - let get_crate_data = &mut |cnum| self.get_crate_data(cnum); self.get_crate_data(def_id.krate) - .each_child_of_item(def_id.index, get_crate_data, - &mut |def, name, vis| { - result.push(ChildItem { - def: def, - name: name, - vis: vis - }); - }); + .each_child_of_item(def_id.index, |child| result.push(child)); result } @@ -567,7 +562,6 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { let mut visible_parent_map = self.visible_parent_map.borrow_mut(); if !visible_parent_map.is_empty() { return visible_parent_map; } - use rustc::middle::cstore::ChildItem; use std::collections::vec_deque::VecDeque; use std::collections::hash_map::Entry; for cnum in (1 .. self.next_crate_num().as_usize()).map(CrateNum::new) { @@ -580,12 +574,12 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { } let mut bfs_queue = &mut VecDeque::new(); - let mut add_child = |bfs_queue: &mut VecDeque<_>, child: ChildItem, parent: DefId| { - let child = if child.vis == ty::Visibility::Public { - child.def.def_id() - } else { + let mut add_child = |bfs_queue: &mut VecDeque<_>, child: def::Export, parent: DefId| { + let child = child.def_id; + + if self.visibility(child) != ty::Visibility::Public { return; - }; + } match visible_parent_map.entry(child) { Entry::Occupied(mut entry) => { diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 05bd9e97234e5..a34daba700091 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -23,7 +23,7 @@ use rustc::hir; use rustc::hir::intravisit::IdRange; use rustc::middle::cstore::{InlinedItem, LinkagePreference}; -use rustc::hir::def::Def; +use rustc::hir::def::{self, Def}; use rustc::hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE}; use rustc::middle::lang_items; use rustc::ty::{ImplContainer, TraitContainer}; @@ -505,6 +505,10 @@ impl<'a, 'tcx> CrateMetadata { self.maybe_get(doc, item_tag::ty).map(|dcx| dcx.typed(tcx).decode()) } + pub fn get_def(&self, index: DefIndex) -> Option { + self.item_family(self.entry(index)).to_def(self.local_def_id(index)) + } + pub fn get_trait_def(&self, item_id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ty::TraitDef<'tcx> { @@ -664,11 +668,8 @@ impl<'a, 'tcx> CrateMetadata { } /// Iterates over each child of the given item. - pub fn each_child_of_item(&self, id: DefIndex, - mut get_crate_data: &mut G, - mut callback: &mut F) - where F: FnMut(Def, ast::Name, ty::Visibility), - G: FnMut(CrateNum) -> Rc, + pub fn each_child_of_item(&self, id: DefIndex, mut callback: F) + where F: FnMut(def::Export) { // Find the item. let item_doc = match self.maybe_entry(id) { @@ -682,15 +683,31 @@ impl<'a, 'tcx> CrateMetadata { }; // Iterate over all children. - for child_index in dcx.seq::() { + for child_index in dcx.seq() { // Get the item. if let Some(child) = self.maybe_entry(child_index) { // Hand off the item to the callback. - let family = self.item_family(child); - if let Family::ForeignMod = family { - self.each_child_of_item(child_index, get_crate_data, callback); - } else if let Some(def) = family.to_def(self.local_def_id(child_index)) { - callback(def, self.item_name(child), self.item_visibility(child)); + match self.item_family(child) { + // FIXME(eddyb) Don't encode these in children. + Family::ForeignMod => { + for child_index in self.get(child, item_tag::children).seq() { + callback(def::Export { + def_id: self.local_def_id(child_index), + name: self.item_name(self.entry(child_index)) + }); + } + continue; + } + Family::Impl | Family::DefaultImpl => continue, + + _ => {} + } + + if let Some(name) = self.maybe_item_name(child) { + callback(def::Export { + def_id: self.local_def_id(child_index), + name: name + }); } } } @@ -700,26 +717,7 @@ impl<'a, 'tcx> CrateMetadata { _ => return }; for exp in reexports { - // This reexport may be in yet another crate. - let crate_data = if exp.def_id.krate == self.cnum { - None - } else { - Some(get_crate_data(exp.def_id.krate)) - }; - let crate_data = match crate_data { - Some(ref cdata) => &**cdata, - None => self - }; - - // Get the item. - if let Some(child) = crate_data.maybe_entry(exp.def_id.index) { - // Hand off the item to the callback. - if let Some(def) = self.item_family(child).to_def(exp.def_id) { - // These items have a public visibility because they're part of - // a public re-export. - callback(def, exp.name, ty::Visibility::Public); - } - } + callback(exp); } } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index e345129b327e9..e690e5198795c 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -373,6 +373,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn encode_struct_ctor(&mut self, ctor_def_id: DefId) { self.encode_def_key(ctor_def_id); self.encode_family(Family::Struct); + self.encode_visibility(ty::Visibility::Public); self.encode_bounds_and_type_for_item(ctor_def_id); self.encode_stability(ctor_def_id); diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 77a01aac73956..1714398f2fed0 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -21,7 +21,6 @@ use ParentLink::{ModuleParentLink, BlockParentLink}; use Resolver; use {resolve_error, resolve_struct_error, ResolutionError}; -use rustc::middle::cstore::ChildItem; use rustc::hir::def::*; use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId}; use rustc::hir::map::DefPathData; @@ -387,10 +386,22 @@ impl<'b> Resolver<'b> { } /// Builds the reduced graph for a single item in an external crate. - fn build_reduced_graph_for_external_crate_def(&mut self, parent: Module<'b>, child: ChildItem) { - let def = child.def; + fn build_reduced_graph_for_external_crate_def(&mut self, parent: Module<'b>, + child: Export) { + let def_id = child.def_id; let name = child.name; - let vis = if parent.is_trait() { ty::Visibility::Public } else { child.vis }; + + let def = if let Some(def) = self.session.cstore.describe_def(def_id) { + def + } else { + return; + }; + + let vis = if parent.is_trait() { + ty::Visibility::Public + } else { + self.session.cstore.visibility(def_id) + }; match def { Def::Mod(_) | Def::Enum(..) => { @@ -416,7 +427,7 @@ impl<'b> Resolver<'b> { name); let _ = self.try_define(parent, name, ValueNS, (def, DUMMY_SP, vis)); } - Def::Trait(def_id) => { + Def::Trait(_) => { debug!("(building reduced graph for external crate) building type {}", name); // If this is a trait, add all the trait item names to the trait @@ -443,7 +454,7 @@ impl<'b> Resolver<'b> { debug!("(building reduced graph for external crate) building type {}", name); let _ = self.try_define(parent, name, TypeNS, (def, DUMMY_SP, vis)); } - Def::Struct(def_id) + Def::Struct(_) if self.session.cstore.def_key(def_id).disambiguated_data.data != DefPathData::StructCtor => { @@ -459,7 +470,7 @@ impl<'b> Resolver<'b> { let fields = self.session.cstore.struct_field_names(def_id); self.structs.insert(def_id, fields); } - Def::Union(def_id) => { + Def::Union(_) => { let _ = self.try_define(parent, name, TypeNS, (def, DUMMY_SP, vis)); // Record the def ID and fields of this union. diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 7ec4918070233..34bcd2ba046e9 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -451,27 +451,27 @@ pub fn all_traits<'a>(ccx: &'a CrateCtxt) -> AllTraits<'a> { fn handle_external_def(ccx: &CrateCtxt, traits: &mut AllTraitsVec, external_mods: &mut FnvHashSet, - def: Def) { - match def { - Def::Trait(did) => { - traits.push(TraitInfo::new(did)); + def_id: DefId) { + match ccx.tcx.sess.cstore.describe_def(def_id) { + Some(Def::Trait(_)) => { + traits.push(TraitInfo::new(def_id)); } - Def::Mod(did) => { - if !external_mods.insert(did) { + Some(Def::Mod(_)) => { + if !external_mods.insert(def_id) { return; } - for child in ccx.tcx.sess.cstore.item_children(did) { - handle_external_def(ccx, traits, external_mods, child.def) + for child in ccx.tcx.sess.cstore.item_children(def_id) { + handle_external_def(ccx, traits, external_mods, child.def_id) } } _ => {} } } for cnum in ccx.tcx.sess.cstore.crates() { - handle_external_def(ccx, &mut traits, &mut external_mods, Def::Mod(DefId { + handle_external_def(ccx, &mut traits, &mut external_mods, DefId { krate: cnum, index: CRATE_DEF_INDEX - })); + }); } *ccx.all_traits.borrow_mut() = Some(traits); diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 855b135b8636a..c4d6ff43eff08 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -498,10 +498,12 @@ fn build_module<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>, // visit each node at most once. let mut visited = FnvHashSet(); for item in tcx.sess.cstore.item_children(did) { - if item.vis == ty::Visibility::Public { - if !visited.insert(item.def) { continue } - if let Some(i) = try_inline_def(cx, tcx, item.def) { - items.extend(i) + if tcx.sess.cstore.visibility(item.def_id) == ty::Visibility::Public { + if !visited.insert(item.def_id) { continue } + if let Some(def) = tcx.sess.cstore.describe_def(item.def_id) { + if let Some(i) = try_inline_def(cx, tcx, def) { + items.extend(i) + } } } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 0acf211a27c53..9f208b7bed70c 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -240,11 +240,7 @@ impl Clean for CrateNum { let root = DefId { krate: self.0, index: CRATE_DEF_INDEX }; cx.tcx_opt().map(|tcx| { for item in tcx.sess.cstore.item_children(root) { - let did = match item.def { - Def::Mod(did) => did, - _ => continue - }; - let attrs = inline::load_attrs(cx, tcx, did); + let attrs = inline::load_attrs(cx, tcx, item.def_id); PrimitiveType::find(&attrs).map(|prim| primitives.push(prim)); } }); diff --git a/src/librustdoc/visit_lib.rs b/src/librustdoc/visit_lib.rs index d93ca75a8da02..285b47fe60abf 100644 --- a/src/librustdoc/visit_lib.rs +++ b/src/librustdoc/visit_lib.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use rustc::middle::cstore::{CrateStore, ChildItem}; +use rustc::middle::cstore::CrateStore; use rustc::middle::privacy::{AccessLevels, AccessLevel}; use rustc::hir::def::Def; use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId}; @@ -64,38 +64,27 @@ impl<'a, 'b, 'tcx> LibEmbargoVisitor<'a, 'b, 'tcx> { } } - pub fn visit_mod(&mut self, did: DefId) { - for item in self.cstore.item_children(did) { - match item.def { - Def::Mod(did) | - Def::Trait(did) | - Def::Struct(did) | - Def::Union(did) | - Def::Enum(did) | - Def::TyAlias(did) | - Def::Fn(did) | - Def::Method(did) | - Def::Static(did, _) | - Def::Const(did) => self.visit_item(did, item), - _ => {} - } + pub fn visit_mod(&mut self, def_id: DefId) { + for item in self.cstore.item_children(def_id) { + self.visit_item(item.def_id); } } - fn visit_item(&mut self, did: DefId, item: ChildItem) { - let inherited_item_level = if item.vis == Visibility::Public { + fn visit_item(&mut self, def_id: DefId) { + let vis = self.cstore.visibility(def_id); + let inherited_item_level = if vis == Visibility::Public { self.prev_level } else { None }; - let item_level = self.update(did, inherited_item_level); + let item_level = self.update(def_id, inherited_item_level); - if let Def::Mod(did) = item.def { + if let Some(Def::Mod(_)) = self.cstore.describe_def(def_id) { let orig_level = self.prev_level; self.prev_level = item_level; - self.visit_mod(did); + self.visit_mod(def_id); self.prev_level = orig_level; } } From a96abca2a4ec14df912b7ebee69dbeac19d630c4 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Fri, 16 Sep 2016 17:25:54 +0300 Subject: [PATCH 28/39] rustc_metadata: replace RBML with a simple and type-safe scheme. --- src/librustc/middle/cstore.rs | 8 +- src/librustc/ty/mod.rs | 5 +- src/librustc_metadata/Cargo.toml | 1 - src/librustc_metadata/astencode.rs | 221 ++- src/librustc_metadata/common.rs | 206 --- src/librustc_metadata/creader.rs | 211 +-- src/librustc_metadata/csearch.rs | 19 +- src/librustc_metadata/cstore.rs | 69 +- src/librustc_metadata/decoder.rs | 957 ++++++------- src/librustc_metadata/encoder.rs | 1530 +++++++++++---------- src/librustc_metadata/index.rs | 118 +- src/librustc_metadata/index_builder.rs | 26 +- src/librustc_metadata/lib.rs | 13 +- src/librustc_metadata/loader.rs | 48 +- src/librustc_metadata/rbml/reader.rs | 411 ------ src/librustc_metadata/rbml/writer.rs | 134 -- src/librustc_metadata/schema.rs | 299 ++++ src/librustc_typeck/collect.rs | 13 + src/librustdoc/clean/mod.rs | 2 +- src/rustc/Cargo.lock | 1 - src/test/run-pass-fulldeps/issue-11881.rs | 6 +- 21 files changed, 1827 insertions(+), 2471 deletions(-) delete mode 100644 src/librustc_metadata/common.rs delete mode 100644 src/librustc_metadata/rbml/reader.rs delete mode 100644 src/librustc_metadata/rbml/writer.rs create mode 100644 src/librustc_metadata/schema.rs diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index dbbd5eca4832e..658825d417e4c 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -138,11 +138,11 @@ pub trait CrateStore<'tcx> { fn item_super_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> ty::GenericPredicates<'tcx>; fn item_generics<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) - -> &'tcx ty::Generics<'tcx>; + -> ty::Generics<'tcx>; fn item_attrs(&self, def_id: DefId) -> Vec; fn trait_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)-> ty::TraitDef<'tcx>; fn adt_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> ty::AdtDefMaster<'tcx>; - fn fn_arg_names(&self, did: DefId) -> Vec; + fn fn_arg_names(&self, did: DefId) -> Vec; fn inherent_implementations_for_type(&self, def_id: DefId) -> Vec; // trait info @@ -299,13 +299,13 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { fn item_super_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> ty::GenericPredicates<'tcx> { bug!("item_super_predicates") } fn item_generics<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) - -> &'tcx ty::Generics<'tcx> { bug!("item_generics") } + -> ty::Generics<'tcx> { bug!("item_generics") } fn item_attrs(&self, def_id: DefId) -> Vec { bug!("item_attrs") } fn trait_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)-> ty::TraitDef<'tcx> { bug!("trait_def") } fn adt_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> ty::AdtDefMaster<'tcx> { bug!("adt_def") } - fn fn_arg_names(&self, did: DefId) -> Vec { bug!("fn_arg_names") } + fn fn_arg_names(&self, did: DefId) -> Vec { bug!("fn_arg_names") } fn inherent_implementations_for_type(&self, def_id: DefId) -> Vec { vec![] } // trait info diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 8171a99beb90f..8a9b2846ac666 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -737,6 +737,9 @@ pub struct GenericPredicates<'tcx> { pub predicates: Vec>, } +impl<'tcx> serialize::UseSpecializedEncodable for GenericPredicates<'tcx> {} +impl<'tcx> serialize::UseSpecializedDecodable for GenericPredicates<'tcx> {} + impl<'a, 'gcx, 'tcx> GenericPredicates<'tcx> { pub fn instantiate(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, substs: &Substs<'tcx>) -> InstantiatedPredicates<'tcx> { @@ -2457,7 +2460,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn lookup_generics(self, did: DefId) -> &'gcx Generics<'gcx> { lookup_locally_or_in_crate_store( "generics", did, &self.generics, - || self.sess.cstore.item_generics(self.global_tcx(), did)) + || self.alloc_generics(self.sess.cstore.item_generics(self.global_tcx(), did))) } /// Given the did of an item, returns its full set of predicates. diff --git a/src/librustc_metadata/Cargo.toml b/src/librustc_metadata/Cargo.toml index fede6f663418c..680d55955bb96 100644 --- a/src/librustc_metadata/Cargo.toml +++ b/src/librustc_metadata/Cargo.toml @@ -13,7 +13,6 @@ flate = { path = "../libflate" } log = { path = "../liblog" } rustc = { path = "../librustc" } rustc_back = { path = "../librustc_back" } -rustc_bitflags = { path = "../librustc_bitflags" } rustc_const_math = { path = "../librustc_const_math" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_errors = { path = "../librustc_errors" } diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs index f48c31fc2f9dd..c9dbedacbc1a5 100644 --- a/src/librustc_metadata/astencode.rs +++ b/src/librustc_metadata/astencode.rs @@ -13,43 +13,92 @@ use rustc::hir::map as ast_map; use rustc::hir::intravisit::{Visitor, IdRangeComputingVisitor, IdRange}; use cstore::CrateMetadata; -use decoder::DecodeContext; use encoder::EncodeContext; +use schema::*; use rustc::middle::cstore::{InlinedItem, InlinedItemRef}; -use rustc::hir::def; +use rustc::middle::const_qualif::ConstQualif; +use rustc::hir::def::{self, Def}; use rustc::hir::def_id::DefId; -use rustc::ty::TyCtxt; +use rustc::ty::{self, TyCtxt, Ty}; use syntax::ast; -use rbml; -use rustc_serialize::{Decodable, Encodable}; +use rustc_serialize::Encodable; -// ______________________________________________________________________ -// Top-level methods. +#[derive(RustcEncodable, RustcDecodable)] +pub struct Ast<'tcx> { + id_range: IdRange, + item: Lazy, + side_tables: LazySeq<(ast::NodeId, TableEntry<'tcx>)> +} + +#[derive(RustcEncodable, RustcDecodable)] +enum TableEntry<'tcx> { + Def(Def), + NodeType(Ty<'tcx>), + ItemSubsts(ty::ItemSubsts<'tcx>), + Adjustment(ty::adjustment::AutoAdjustment<'tcx>), + ConstQualif(ConstQualif) +} -pub fn encode_inlined_item(ecx: &mut EncodeContext, ii: InlinedItemRef) { - ecx.tag(::common::item_tag::ast, |ecx| { - let mut visitor = IdRangeComputingVisitor::new(); +impl<'a, 'tcx> EncodeContext<'a, 'tcx> { + pub fn encode_inlined_item(&mut self, ii: InlinedItemRef) -> Lazy> { + let mut id_visitor = IdRangeComputingVisitor::new(); match ii { - InlinedItemRef::Item(_, i) => visitor.visit_item(i), - InlinedItemRef::TraitItem(_, ti) => visitor.visit_trait_item(ti), - InlinedItemRef::ImplItem(_, ii) => visitor.visit_impl_item(ii) + InlinedItemRef::Item(_, i) => id_visitor.visit_item(i), + InlinedItemRef::TraitItem(_, ti) => id_visitor.visit_trait_item(ti), + InlinedItemRef::ImplItem(_, ii) => id_visitor.visit_impl_item(ii) } - visitor.result().encode(ecx).unwrap(); - ii.encode(ecx).unwrap(); + let ii_pos = self.position(); + ii.encode(self).unwrap(); + + let tables_pos = self.position(); + let tables_count = { + let mut visitor = SideTableEncodingIdVisitor { + ecx: self, + count: 0 + }; + match ii { + InlinedItemRef::Item(_, i) => visitor.visit_item(i), + InlinedItemRef::TraitItem(_, ti) => visitor.visit_trait_item(ti), + InlinedItemRef::ImplItem(_, ii) => visitor.visit_impl_item(ii) + } + visitor.count + }; + + self.lazy(&Ast { + id_range: id_visitor.result(), + item: Lazy::with_position(ii_pos), + side_tables: LazySeq::with_position_and_length(tables_pos, tables_count) + }) + } +} + +struct SideTableEncodingIdVisitor<'a, 'b:'a, 'tcx:'b> { + ecx: &'a mut EncodeContext<'b, 'tcx>, + count: usize +} + +impl<'a, 'b, 'tcx, 'v> Visitor<'v> for SideTableEncodingIdVisitor<'a, 'b, 'tcx> { + fn visit_id(&mut self, id: ast::NodeId) { + debug!("Encoding side tables for id {}", id); - let mut visitor = SideTableEncodingIdVisitor { - ecx: ecx + let tcx = self.ecx.tcx; + let mut encode = |entry: Option| { + if let Some(entry) = entry { + (id, entry).encode(self.ecx).unwrap(); + self.count += 1; + } }; - match ii { - InlinedItemRef::Item(_, i) => visitor.visit_item(i), - InlinedItemRef::TraitItem(_, ti) => visitor.visit_trait_item(ti), - InlinedItemRef::ImplItem(_, ii) => visitor.visit_impl_item(ii) - } - }); + + encode(tcx.expect_def_or_none(id).map(TableEntry::Def)); + encode(tcx.node_types().get(&id).cloned().map(TableEntry::NodeType)); + encode(tcx.tables.borrow().item_substs.get(&id).cloned().map(TableEntry::ItemSubsts)); + encode(tcx.tables.borrow().adjustments.get(&id).cloned().map(TableEntry::Adjustment)); + encode(tcx.const_qualif_map.borrow().get(&id).cloned().map(TableEntry::ConstQualif)); + } } /// Decodes an item from its AST in the cdata's metadata and adds it to the @@ -58,17 +107,19 @@ pub fn decode_inlined_item<'a, 'tcx>(cdata: &CrateMetadata, tcx: TyCtxt<'a, 'tcx, 'tcx>, parent_def_path: ast_map::DefPath, parent_did: DefId, - ast_doc: rbml::Doc, + ast: Ast<'tcx>, orig_did: DefId) -> &'tcx InlinedItem { debug!("> Decoding inlined fn: {:?}", tcx.item_path_str(orig_did)); - let dcx = &mut DecodeContext::new(ast_doc, Some(cdata)).typed(tcx); - dcx.from_id_range = IdRange::decode(dcx).unwrap(); - let cnt = dcx.from_id_range.max.as_usize() - dcx.from_id_range.min.as_usize(); - dcx.to_id_range.min = tcx.sess.reserve_node_ids(cnt); - dcx.to_id_range.max = ast::NodeId::new(dcx.to_id_range.min.as_usize() + cnt); - let ii = InlinedItem::decode(dcx).unwrap(); + let cnt = ast.id_range.max.as_usize() - ast.id_range.min.as_usize(); + let start = tcx.sess.reserve_node_ids(cnt); + let id_ranges = [ast.id_range, IdRange { + min: start, + max: ast::NodeId::new(start.as_usize() + cnt) + }]; + + let ii = ast.item.decode((cdata, tcx, id_ranges)); let ii = ast_map::map_decoded_item(&tcx.map, parent_def_path, parent_did, @@ -83,107 +134,25 @@ pub fn decode_inlined_item<'a, 'tcx>(cdata: &CrateMetadata, let inlined_did = tcx.map.local_def_id(item_node_id); tcx.register_item_type(inlined_did, tcx.lookup_item_type(orig_did)); - decode_side_tables(dcx, ast_doc); - - ii -} - -// ______________________________________________________________________ -// Encoding and decoding the side tables - -impl<'a, 'tcx> EncodeContext<'a, 'tcx> { - fn tag(&mut self, - tag_id: usize, - f: F) where - F: FnOnce(&mut Self), - { - self.start_tag(tag_id).unwrap(); - f(self); - self.end_tag().unwrap(); - } - - fn entry(&mut self, table: Table, id: ast::NodeId) { - table.encode(self).unwrap(); - id.encode(self).unwrap(); - } -} - -struct SideTableEncodingIdVisitor<'a, 'b:'a, 'tcx:'b> { - ecx: &'a mut EncodeContext<'b, 'tcx>, -} - -impl<'a, 'b, 'tcx, 'v> Visitor<'v> for SideTableEncodingIdVisitor<'a, 'b, 'tcx> { - fn visit_id(&mut self, id: ast::NodeId) { - encode_side_tables_for_id(self.ecx, id) - } -} - -#[derive(RustcEncodable, RustcDecodable, Debug)] -enum Table { - Def, - NodeType, - ItemSubsts, - Adjustment, - ConstQualif -} - -fn encode_side_tables_for_id(ecx: &mut EncodeContext, id: ast::NodeId) { - let tcx = ecx.tcx; - - debug!("Encoding side tables for id {}", id); - - if let Some(def) = tcx.expect_def_or_none(id) { - ecx.entry(Table::Def, id); - def.encode(ecx).unwrap(); - } - - if let Some(ty) = tcx.node_types().get(&id) { - ecx.entry(Table::NodeType, id); - ty.encode(ecx).unwrap(); - } - - if let Some(item_substs) = tcx.tables.borrow().item_substs.get(&id) { - ecx.entry(Table::ItemSubsts, id); - item_substs.substs.encode(ecx).unwrap(); - } - - if let Some(adjustment) = tcx.tables.borrow().adjustments.get(&id) { - ecx.entry(Table::Adjustment, id); - adjustment.encode(ecx).unwrap(); - } - - if let Some(qualif) = tcx.const_qualif_map.borrow().get(&id) { - ecx.entry(Table::ConstQualif, id); - qualif.encode(ecx).unwrap(); - } -} - -fn decode_side_tables(dcx: &mut DecodeContext, ast_doc: rbml::Doc) { - while dcx.opaque.position() < ast_doc.end { - let table = Decodable::decode(dcx).unwrap(); - let id = Decodable::decode(dcx).unwrap(); - debug!("decode_side_tables: entry for id={}, table={:?}", id, table); - match table { - Table::Def => { - let def = Decodable::decode(dcx).unwrap(); - dcx.tcx().def_map.borrow_mut().insert(id, def::PathResolution::new(def)); + for (id, entry) in ast.side_tables.decode((cdata, tcx, id_ranges)) { + match entry { + TableEntry::Def(def) => { + tcx.def_map.borrow_mut().insert(id, def::PathResolution::new(def)); } - Table::NodeType => { - let ty = Decodable::decode(dcx).unwrap(); - dcx.tcx().node_type_insert(id, ty); + TableEntry::NodeType(ty) => { + tcx.node_type_insert(id, ty); } - Table::ItemSubsts => { - let item_substs = Decodable::decode(dcx).unwrap(); - dcx.tcx().tables.borrow_mut().item_substs.insert(id, item_substs); + TableEntry::ItemSubsts(item_substs) => { + tcx.tables.borrow_mut().item_substs.insert(id, item_substs); } - Table::Adjustment => { - let adj = Decodable::decode(dcx).unwrap(); - dcx.tcx().tables.borrow_mut().adjustments.insert(id, adj); + TableEntry::Adjustment(adj) => { + tcx.tables.borrow_mut().adjustments.insert(id, adj); } - Table::ConstQualif => { - let qualif = Decodable::decode(dcx).unwrap(); - dcx.tcx().const_qualif_map.borrow_mut().insert(id, qualif); + TableEntry::ConstQualif(qualif) => { + tcx.const_qualif_map.borrow_mut().insert(id, qualif); } } } + + ii } diff --git a/src/librustc_metadata/common.rs b/src/librustc_metadata/common.rs deleted file mode 100644 index f30551cadd97a..0000000000000 --- a/src/librustc_metadata/common.rs +++ /dev/null @@ -1,206 +0,0 @@ -// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![allow(non_camel_case_types, non_upper_case_globals)] - -use rustc::hir; -use rustc::hir::def; -use rustc::hir::def_id::{DefIndex, DefId}; -use rustc::ty; -use rustc::session::config::PanicStrategy; - -#[derive(Clone, Copy, Debug, PartialEq, RustcEncodable, RustcDecodable)] -pub enum Family { - ImmStatic, - MutStatic, - ForeignImmStatic, - ForeignMutStatic, - Fn, - ForeignFn, - Method, - AssociatedType, - Type, - Mod, - ForeignMod, - Enum, - Variant, - Impl, - DefaultImpl, - Trait, - Struct, - Union, - Field, - Const, - AssociatedConst, - Closure -} - -// NB: increment this if you change the format of metadata such that -// rustc_version can't be found. -pub const metadata_encoding_version : &'static [u8] = &[b'r', b'u', b's', b't', 0, 0, 0, 2]; - -// GAP 0x7c -// GAP 0x108 -pub fn rustc_version() -> String { - format!( - "rustc {}", - option_env!("CFG_VERSION").unwrap_or("unknown version") - ) -} - -#[derive(RustcEncodable, RustcDecodable)] -pub struct CrateInfo { - pub name: String, - pub triple: String, - pub hash: hir::svh::Svh, - pub disambiguator: String, - pub panic_strategy: PanicStrategy, - pub plugin_registrar_fn: Option, - pub macro_derive_registrar: Option -} - -pub mod root_tag { - pub const rustc_version: usize = 0x10f; - - pub const crate_info: usize = 0x104; - - pub const index: usize = 0x110; - pub const crate_deps: usize = 0x102; - pub const dylib_dependency_formats: usize = 0x106; - pub const native_libraries: usize = 0x10a; - pub const lang_items: usize = 0x107; - pub const lang_items_missing: usize = 0x76; - pub const impls: usize = 0x109; - pub const reachable_ids: usize = 0x10c; - pub const macro_defs: usize = 0x10e; - pub const codemap: usize = 0xa1; -} - -#[derive(RustcEncodable, RustcDecodable)] -pub struct ModData { - pub reexports: Vec -} - -#[derive(RustcEncodable, RustcDecodable)] -pub struct VariantData { - pub kind: ty::VariantKind, - pub disr: u64, - - /// If this is a struct's only variant, this - /// is the index of the "struct ctor" item. - pub struct_ctor: Option -} - -#[derive(RustcEncodable, RustcDecodable)] -pub struct TraitData { - pub unsafety: hir::Unsafety, - pub paren_sugar: bool, - pub has_default_impl: bool -} - -#[derive(RustcEncodable, RustcDecodable)] -pub struct ImplData { - pub polarity: hir::ImplPolarity, - pub parent_impl: Option, - pub coerce_unsized_kind: Option, -} - -#[derive(RustcEncodable, RustcDecodable)] -pub struct TraitAssociatedData { - pub has_default: bool -} - -#[derive(RustcEncodable, RustcDecodable)] -pub struct ImplAssociatedData { - pub defaultness: hir::Defaultness, - pub constness: hir::Constness -} - -#[derive(RustcEncodable, RustcDecodable)] -pub struct FnData { - pub constness: hir::Constness -} - -#[derive(RustcEncodable, RustcDecodable)] -pub struct ClosureData { - pub kind: ty::ClosureKind -} - -#[derive(RustcEncodable, RustcDecodable)] -pub enum EntryData { - Other, - Mod(ModData), - Variant(VariantData), - Trait(TraitData), - Impl(ImplData), - TraitAssociated(TraitAssociatedData), - ImplAssociated(ImplAssociatedData), - Fn(FnData), - Closure(ClosureData) -} - -#[derive(RustcEncodable, RustcDecodable)] -pub struct TraitTypedData<'tcx> { - pub trait_ref: ty::TraitRef<'tcx> -} - -#[derive(RustcEncodable, RustcDecodable)] -pub struct ImplTypedData<'tcx> { - pub trait_ref: Option> -} - -#[derive(RustcEncodable, RustcDecodable)] -pub struct MethodTypedData<'tcx> { - pub explicit_self: ty::ExplicitSelfCategory<'tcx> -} - -#[derive(RustcEncodable, RustcDecodable)] -pub struct ClosureTypedData<'tcx> { - pub ty: ty::ClosureTy<'tcx> -} - -#[derive(RustcEncodable, RustcDecodable)] -pub enum EntryTypedData<'tcx> { - Other, - Trait(TraitTypedData<'tcx>), - Impl(ImplTypedData<'tcx>), - Method(MethodTypedData<'tcx>), - Closure(ClosureTypedData<'tcx>) -} - -pub mod item_tag { - pub const def_key: usize = 0x2c; - pub const family: usize = 0x24; - pub const attributes: usize = 0x101; - pub const visibility: usize = 0x78; - pub const children: usize = 0x7b; - pub const stability: usize = 0x88; - pub const deprecation: usize = 0xa7; - - pub const ty: usize = 0x25; - pub const inherent_impls: usize = 0x79; - pub const variances: usize = 0x43; - pub const generics: usize = 0x8f; - pub const predicates: usize = 0x95; - pub const super_predicates: usize = 0xa3; - - pub const ast: usize = 0x50; - pub const mir: usize = 0x52; - - pub const data: usize = 0x3c; - pub const typed_data: usize = 0x3d; - - pub const fn_arg_names: usize = 0x85; -} - -/// The shorthand encoding uses an enum's variant index `usize` -/// and is offset by this value so it never matches a real variant. -/// This offset is also chosen so that the first byte is never < 0x80. -pub const SHORTHAND_OFFSET: usize = 0x80; diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 77a583f7379c1..95be77c24f46e 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -8,13 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![allow(non_camel_case_types)] - //! Validates all used crates and extern libraries and loads their metadata -use common::CrateInfo; use cstore::{self, CStore, CrateSource, MetadataBlob}; use loader::{self, CratePaths}; +use schema::CrateRoot; use rustc::hir::def_id::{CrateNum, DefIndex}; use rustc::hir::svh::Svh; @@ -34,12 +32,11 @@ use std::fs; use syntax::ast; use syntax::abi::Abi; -use syntax::codemap; use syntax::parse; use syntax::attr; use syntax::parse::token::InternedString; use syntax::visit; -use syntax_pos::{self, Span, mk_sp, Pos}; +use syntax_pos::{self, Span, mk_sp}; use log; struct LocalCrateReader<'a> { @@ -148,7 +145,7 @@ impl Deref for PMDSource { fn deref(&self) -> &MetadataBlob { match *self { - PMDSource::Registered(ref cmd) => &cmd.data, + PMDSource::Registered(ref cmd) => &cmd.blob, PMDSource::Owned(ref lib) => &lib.metadata } } @@ -261,28 +258,28 @@ impl<'a> CrateReader<'a> { fn verify_no_symbol_conflicts(&self, span: Span, - info: &CrateInfo) { + root: &CrateRoot) { // Check for (potential) conflicts with the local crate - if self.local_crate_name == info.name && - self.sess.local_crate_disambiguator() == &info.disambiguator[..] { + if self.local_crate_name == root.name && + self.sess.local_crate_disambiguator() == &root.disambiguator[..] { span_fatal!(self.sess, span, E0519, "the current crate is indistinguishable from one of its \ dependencies: it has the same crate-name `{}` and was \ compiled with the same `-C metadata` arguments. This \ will result in symbol conflicts between the two.", - info.name) + root.name) } // Check for conflicts with any crate loaded so far self.cstore.iter_crate_data(|_, other| { - if other.name() == info.name && // same crate-name - other.disambiguator() == info.disambiguator && // same crate-disambiguator - other.hash() != info.hash { // but different SVH + if other.name() == root.name && // same crate-name + other.disambiguator() == root.disambiguator && // same crate-disambiguator + other.hash() != root.hash { // but different SVH span_fatal!(self.sess, span, E0523, "found two different crates with name `{}` that are \ not distinguished by differing `-C metadata`. This \ will result in symbol conflicts between the two.", - info.name) + root.name) } }); } @@ -297,8 +294,8 @@ impl<'a> CrateReader<'a> { -> (CrateNum, Rc, cstore::CrateSource) { info!("register crate `extern crate {} as {}`", name, ident); - let crate_info = lib.metadata.get_crate_info(); - self.verify_no_symbol_conflicts(span, &crate_info); + let crate_root = lib.metadata.get_root(); + self.verify_no_symbol_conflicts(span, &crate_root); // Claim this crate number and cache it let cnum = self.next_crate_num; @@ -319,9 +316,9 @@ impl<'a> CrateReader<'a> { let loader::Library { dylib, rlib, metadata } = lib; - let cnum_map = self.resolve_crate_deps(root, &metadata, cnum, span); + let cnum_map = self.resolve_crate_deps(root, &crate_root, &metadata, cnum, span); - if crate_info.macro_derive_registrar.is_some() { + if crate_root.macro_derive_registrar.is_some() { self.sess.span_err(span, "crates of the `rustc-macro` crate type \ cannot be linked at runtime"); } @@ -329,10 +326,9 @@ impl<'a> CrateReader<'a> { let cmeta = Rc::new(cstore::CrateMetadata { name: name.to_string(), extern_crate: Cell::new(None), - info: crate_info, - index: metadata.load_index(), - key_map: metadata.load_key_map(), - data: metadata, + key_map: metadata.load_key_map(crate_root.index), + root: crate_root, + blob: metadata, cnum_map: RefCell::new(cnum_map), cnum: cnum, codemap_import_info: RefCell::new(vec![]), @@ -416,11 +412,11 @@ impl<'a> CrateReader<'a> { // Note that we only do this for target triple crates, though, as we // don't want to match a host crate against an equivalent target one // already loaded. - let crate_info = library.metadata.get_crate_info(); + let root = library.metadata.get_root(); if loader.triple == self.sess.opts.target_triple { let mut result = LoadResult::Loaded(library); self.cstore.iter_crate_data(|cnum, data| { - if data.name() == crate_info.name && crate_info.hash == data.hash() { + if data.name() == root.name && root.hash == data.hash() { assert!(loader.hash.is_none()); info!("load success, going to previous cnum: {}", cnum); result = LoadResult::Previous(cnum); @@ -467,6 +463,7 @@ impl<'a> CrateReader<'a> { // Go through the crate metadata and load any crates that it references fn resolve_crate_deps(&mut self, root: &Option, + crate_root: &CrateRoot, metadata: &MetadataBlob, krate: CrateNum, span: Span) @@ -474,16 +471,17 @@ impl<'a> CrateReader<'a> { debug!("resolving deps of external crate"); // The map from crate numbers in the crate we're resolving to local crate // numbers - let map: FnvHashMap<_, _> = metadata.get_crate_deps().iter().map(|dep| { + let deps = crate_root.crate_deps.decode(metadata); + let map: FnvHashMap<_, _> = deps.enumerate().map(|(crate_num, dep)| { debug!("resolving dep crate {} hash: `{}`", dep.name, dep.hash); let (local_cnum, ..) = self.resolve_crate(root, - &dep.name, - &dep.name, + &dep.name.as_str(), + &dep.name.as_str(), Some(&dep.hash), span, PathKind::Dependency, dep.explicitly_linked); - (dep.cnum, local_cnum) + (CrateNum::new(crate_num + 1), local_cnum) }).collect(); let max_cnum = map.values().cloned().max().map(|cnum| cnum.as_u32()).unwrap_or(0); @@ -568,21 +566,21 @@ impl<'a> CrateReader<'a> { let ci = self.extract_crate_info(item).unwrap(); let ekrate = self.read_extension_crate(item.span, &ci); - let crate_info = ekrate.metadata.get_crate_info(); + let root = ekrate.metadata.get_root(); let source_name = format!("<{} macros>", item.ident); let mut ret = Macros { macro_rules: Vec::new(), custom_derive_registrar: None, - svh: crate_info.hash, + svh: root.hash, dylib: None, }; - ekrate.metadata.each_exported_macro(|name, attrs, span, body| { + for def in root.macro_defs.decode(&*ekrate.metadata) { // NB: Don't use parse::parse_tts_from_source_str because it parses with // quote_depth > 0. let mut p = parse::new_parser_from_source_str(&self.sess.parse_sess, self.local_crate_config.clone(), source_name.clone(), - body); + def.body); let lo = p.span.lo; let body = match p.parse_all_token_trees() { Ok(body) => body, @@ -595,13 +593,13 @@ impl<'a> CrateReader<'a> { let local_span = mk_sp(lo, p.last_span.hi); // Mark the attrs as used - for attr in &attrs { + for attr in &def.attrs { attr::mark_used(attr); } ret.macro_rules.push(ast::MacroDef { - ident: ast::Ident::with_empty_ctxt(name), - attrs: attrs, + ident: ast::Ident::with_empty_ctxt(def.name), + attrs: def.attrs, id: ast::DUMMY_NODE_ID, span: local_span, imported_from: Some(item.ident), @@ -613,11 +611,10 @@ impl<'a> CrateReader<'a> { body: body, }); self.sess.imported_macro_spans.borrow_mut() - .insert(local_span, (name.as_str().to_string(), span)); - true - }); + .insert(local_span, (def.name.as_str().to_string(), def.span)); + } - match crate_info.macro_derive_registrar { + match root.macro_derive_registrar { Some(id) => ret.custom_derive_registrar = Some(id), // If this crate is not a rustc-macro crate then we might be able to @@ -671,10 +668,10 @@ impl<'a> CrateReader<'a> { span_fatal!(self.sess, span, E0456, "{}", &message[..]); } - let crate_info = ekrate.metadata.get_crate_info(); - match (ekrate.dylib.as_ref(), crate_info.plugin_registrar_fn) { + let root = ekrate.metadata.get_root(); + match (ekrate.dylib.as_ref(), root.plugin_registrar_fn) { (Some(dylib), Some(reg)) => { - Some((dylib.to_path_buf(), crate_info.hash, reg)) + Some((dylib.to_path_buf(), root.hash, reg)) } (None, Some(_)) => { span_err!(self.sess, span, E0457, @@ -1086,133 +1083,3 @@ pub fn read_local_crates(sess: & Session, dep_graph: &DepGraph) { LocalCrateReader::new(sess, cstore, defs, krate, local_crate_name).read_crates(dep_graph) } - -/// Imports the codemap from an external crate into the codemap of the crate -/// currently being compiled (the "local crate"). -/// -/// The import algorithm works analogous to how AST items are inlined from an -/// external crate's metadata: -/// For every FileMap in the external codemap an 'inline' copy is created in the -/// local codemap. The correspondence relation between external and local -/// FileMaps is recorded in the `ImportedFileMap` objects returned from this -/// function. When an item from an external crate is later inlined into this -/// crate, this correspondence information is used to translate the span -/// information of the inlined item so that it refers the correct positions in -/// the local codemap (see `>`). -/// -/// The import algorithm in the function below will reuse FileMaps already -/// existing in the local codemap. For example, even if the FileMap of some -/// source file of libstd gets imported many times, there will only ever be -/// one FileMap object for the corresponding file in the local codemap. -/// -/// Note that imported FileMaps do not actually contain the source code of the -/// file they represent, just information about length, line breaks, and -/// multibyte characters. This information is enough to generate valid debuginfo -/// for items inlined from other crates. -pub fn import_codemap(local_codemap: &codemap::CodeMap, - metadata: &MetadataBlob) - -> Vec { - let external_codemap = metadata.get_imported_filemaps(); - - let imported_filemaps = external_codemap.into_iter().map(|filemap_to_import| { - // Try to find an existing FileMap that can be reused for the filemap to - // be imported. A FileMap is reusable if it is exactly the same, just - // positioned at a different offset within the codemap. - let reusable_filemap = { - local_codemap.files - .borrow() - .iter() - .find(|fm| are_equal_modulo_startpos(&fm, &filemap_to_import)) - .map(|rc| rc.clone()) - }; - - match reusable_filemap { - Some(fm) => { - cstore::ImportedFileMap { - original_start_pos: filemap_to_import.start_pos, - original_end_pos: filemap_to_import.end_pos, - translated_filemap: fm - } - } - None => { - // We can't reuse an existing FileMap, so allocate a new one - // containing the information we need. - let syntax_pos::FileMap { - name, - abs_path, - start_pos, - end_pos, - lines, - multibyte_chars, - .. - } = filemap_to_import; - - let source_length = (end_pos - start_pos).to_usize(); - - // Translate line-start positions and multibyte character - // position into frame of reference local to file. - // `CodeMap::new_imported_filemap()` will then translate those - // coordinates to their new global frame of reference when the - // offset of the FileMap is known. - let mut lines = lines.into_inner(); - for pos in &mut lines { - *pos = *pos - start_pos; - } - let mut multibyte_chars = multibyte_chars.into_inner(); - for mbc in &mut multibyte_chars { - mbc.pos = mbc.pos - start_pos; - } - - let local_version = local_codemap.new_imported_filemap(name, - abs_path, - source_length, - lines, - multibyte_chars); - cstore::ImportedFileMap { - original_start_pos: start_pos, - original_end_pos: end_pos, - translated_filemap: local_version - } - } - } - }).collect(); - - return imported_filemaps; - - fn are_equal_modulo_startpos(fm1: &syntax_pos::FileMap, - fm2: &syntax_pos::FileMap) - -> bool { - if fm1.name != fm2.name { - return false; - } - - let lines1 = fm1.lines.borrow(); - let lines2 = fm2.lines.borrow(); - - if lines1.len() != lines2.len() { - return false; - } - - for (&line1, &line2) in lines1.iter().zip(lines2.iter()) { - if (line1 - fm1.start_pos) != (line2 - fm2.start_pos) { - return false; - } - } - - let multibytes1 = fm1.multibyte_chars.borrow(); - let multibytes2 = fm2.multibyte_chars.borrow(); - - if multibytes1.len() != multibytes2.len() { - return false; - } - - for (mb1, mb2) in multibytes1.iter().zip(multibytes2.iter()) { - if (mb1.bytes != mb2.bytes) || - ((mb1.pos - fm1.start_pos) != (mb2.pos - fm2.start_pos)) { - return false; - } - } - - true - } -} diff --git a/src/librustc_metadata/csearch.rs b/src/librustc_metadata/csearch.rs index 8569dbcd50733..f508c5dc9cfb0 100644 --- a/src/librustc_metadata/csearch.rs +++ b/src/librustc_metadata/csearch.rs @@ -9,9 +9,9 @@ // except according to those terms. use cstore; -use common; use encoder; use loader; +use schema; use rustc::middle::cstore::{InlinedItem, CrateStore, CrateSource, ExternCrate}; use rustc::middle::cstore::{NativeLibraryKind, LinkMeta, LinkagePreference}; @@ -97,7 +97,7 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { } fn item_generics<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) - -> &'tcx ty::Generics<'tcx> + -> ty::Generics<'tcx> { self.dep_graph.read(DepNode::MetaData(def)); self.get_crate_data(def.krate).get_generics(def.index, tcx) @@ -121,7 +121,7 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { self.get_crate_data(def.krate).get_adt_def(def.index, tcx) } - fn fn_arg_names(&self, did: DefId) -> Vec + fn fn_arg_names(&self, did: DefId) -> Vec { self.dep_graph.read(DepNode::MetaData(did)); self.get_crate_data(did.krate).get_fn_arg_names(did.index) @@ -140,10 +140,7 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { fn inherent_implementations_for_type(&self, def_id: DefId) -> Vec { self.dep_graph.read(DepNode::MetaData(def_id)); - let mut result = vec![]; - self.get_crate_data(def_id.krate) - .each_inherent_implementation_for_type(def_id.index, |iid| result.push(iid)); - result + self.get_crate_data(def_id.krate).get_inherent_implementations_for_type(def_id.index) } fn implementations_of_trait(&self, filter: Option) -> Vec @@ -153,9 +150,7 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { } let mut result = vec![]; self.iter_crate_data(|_, cdata| { - cdata.each_implementation_for_trait(filter, &mut |iid| { - result.push(iid) - }) + cdata.get_implementations_for_trait(filter, &mut result) }); result } @@ -308,7 +303,7 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { fn plugin_registrar_fn(&self, cnum: CrateNum) -> Option { - self.get_crate_data(cnum).info.plugin_registrar_fn.map(|index| DefId { + self.get_crate_data(cnum).root.plugin_registrar_fn.map(|index| DefId { krate: cnum, index: index }) @@ -552,7 +547,7 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { fn metadata_encoding_version(&self) -> &[u8] { - common::metadata_encoding_version + schema::METADATA_HEADER } /// Returns a map from a sufficiently visible external item (i.e. an external item that is diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index 4151f98b3daee..0a1ff70a0497e 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -11,12 +11,8 @@ // The crate store - a central repo for information collected about external // crates and libraries -pub use self::MetadataBlob::*; - -use common; -use creader; -use index; use loader; +use schema; use rustc::dep_graph::DepGraph; use rustc::hir::def_id::{CRATE_DEF_INDEX, CrateNum, DefIndex, DefId}; @@ -27,13 +23,12 @@ use rustc::session::config::PanicStrategy; use rustc_data_structures::indexed_vec::IndexVec; use rustc::util::nodemap::{FnvHashMap, NodeMap, NodeSet, DefIdMap, FnvHashSet}; -use std::cell::{RefCell, Ref, Cell}; +use std::cell::{RefCell, Cell}; use std::rc::Rc; use std::path::PathBuf; use flate::Bytes; use syntax::ast::{self, Ident}; use syntax::attr; -use syntax::codemap; use syntax_pos; pub use rustc::middle::cstore::{NativeLibraryKind, LinkagePreference}; @@ -47,12 +42,12 @@ pub use rustc::middle::cstore::{CrateSource, LinkMeta}; pub type CrateNumMap = IndexVec; pub enum MetadataBlob { - MetadataVec(Bytes), - MetadataArchive(loader::ArchiveMetadata), + Inflated(Bytes), + Archive(loader::ArchiveMetadata), } /// Holds information about a syntax_pos::FileMap imported from another crate. -/// See creader::import_codemap() for more information. +/// See `imported_filemaps()` for more information. pub struct ImportedFileMap { /// This FileMap's byte-offset within the codemap of its original crate pub original_start_pos: syntax_pos::BytePos, @@ -70,13 +65,12 @@ pub struct CrateMetadata { /// (e.g., by the allocator) pub extern_crate: Cell>, - pub data: MetadataBlob, + pub blob: MetadataBlob, pub cnum_map: RefCell, pub cnum: CrateNum, pub codemap_import_info: RefCell>, - pub info: common::CrateInfo, - pub index: index::Index, + pub root: schema::CrateRoot, /// For each public item in this crate, we encode a key. When the /// crate is loaded, we read all the keys and put them in this @@ -294,23 +288,9 @@ impl CStore { } impl CrateMetadata { - pub fn name(&self) -> &str { &self.info.name } - pub fn hash(&self) -> Svh { self.info.hash } - pub fn disambiguator(&self) -> &str { &self.info.disambiguator } - pub fn imported_filemaps<'a>(&'a self, codemap: &codemap::CodeMap) - -> Ref<'a, Vec> { - let filemaps = self.codemap_import_info.borrow(); - if filemaps.is_empty() { - drop(filemaps); - let filemaps = creader::import_codemap(codemap, &self.data); - - // This shouldn't borrow twice, but there is no way to downgrade RefMut to Ref. - *self.codemap_import_info.borrow_mut() = filemaps; - self.codemap_import_info.borrow() - } else { - filemaps - } - } + pub fn name(&self) -> &str { &self.root.name } + pub fn hash(&self) -> Svh { self.root.hash } + pub fn disambiguator(&self) -> &str { &self.root.disambiguator } pub fn is_staged_api(&self) -> bool { self.get_item_attrs(CRATE_DEF_INDEX).iter().any(|attr| { @@ -349,33 +329,6 @@ impl CrateMetadata { } pub fn panic_strategy(&self) -> PanicStrategy { - self.info.panic_strategy.clone() - } -} - -impl MetadataBlob { - pub fn as_slice_raw<'a>(&'a self) -> &'a [u8] { - match *self { - MetadataVec(ref vec) => &vec[..], - MetadataArchive(ref ar) => ar.as_slice(), - } - } - - pub fn as_slice<'a>(&'a self) -> &'a [u8] { - let slice = self.as_slice_raw(); - let len_offset = 4 + common::metadata_encoding_version.len(); - if slice.len() < len_offset+4 { - &[] // corrupt metadata - } else { - let len = (((slice[len_offset+0] as u32) << 24) | - ((slice[len_offset+1] as u32) << 16) | - ((slice[len_offset+2] as u32) << 8) | - ((slice[len_offset+3] as u32) << 0)) as usize; - if len <= slice.len() - 4 - len_offset { - &slice[len_offset + 4..len_offset + len + 4] - } else { - &[] // corrupt or old metadata - } - } + self.root.panic_strategy.clone() } } diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index a34daba700091..7a4d3ed657a1e 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -11,11 +11,10 @@ // Decoding metadata from a single crate's metadata use astencode::decode_inlined_item; -use cstore::{CrateMetadata, MetadataBlob, NativeLibraryKind}; -use common::*; -use index; +use cstore::{self, CrateMetadata, MetadataBlob, NativeLibraryKind}; +use index::Index; +use schema::*; -use rustc::hir::svh::Svh; use rustc::hir::map as hir_map; use rustc::hir::map::{DefKey, DefPathData}; use rustc::util::nodemap::FnvHashMap; @@ -26,7 +25,6 @@ use rustc::middle::cstore::{InlinedItem, LinkagePreference}; use rustc::hir::def::{self, Def}; use rustc::hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE}; use rustc::middle::lang_items; -use rustc::ty::{ImplContainer, TraitContainer}; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::subst::Substs; @@ -34,73 +32,119 @@ use rustc_const_math::ConstInt; use rustc::mir::repr::Mir; +use std::cell::Ref; use std::io; use std::mem; use std::rc::Rc; use std::str; use std::u32; -use rbml; use rustc_serialize::{Decodable, Decoder, SpecializedDecoder, opaque}; use syntax::attr; use syntax::ast::{self, NodeId}; +use syntax::codemap; use syntax::parse::token; -use syntax_pos::{self, Span, BytePos}; +use syntax_pos::{self, Span, BytePos, Pos}; pub struct DecodeContext<'a, 'tcx: 'a> { - pub opaque: opaque::Decoder<'a>, + opaque: opaque::Decoder<'a>, tcx: Option>, cdata: Option<&'a CrateMetadata>, - pub from_id_range: IdRange, - pub to_id_range: IdRange, + from_id_range: IdRange, + to_id_range: IdRange, // Cache the last used filemap for translating spans as an optimization. last_filemap_index: usize, } -impl<'a, 'tcx> DecodeContext<'a, 'tcx> { - pub fn new(doc: rbml::Doc<'a>, cdata: Option<&'a CrateMetadata>) - -> DecodeContext<'a, 'tcx> { +/// Abstract over the various ways one can create metadata decoders. +pub trait Metadata<'a, 'tcx>: Copy { + fn raw_bytes(self) -> &'a [u8]; + fn cdata(self) -> Option<&'a CrateMetadata> { None } + fn tcx(self) -> Option> { None } + + fn decoder(self, pos: usize) -> DecodeContext<'a, 'tcx> { let id_range = IdRange { min: NodeId::from_u32(u32::MIN), max: NodeId::from_u32(u32::MAX) }; DecodeContext { - opaque: opaque::Decoder::new(doc.data, doc.start), - cdata: cdata, - tcx: None, + opaque: opaque::Decoder::new(self.raw_bytes(), pos), + cdata: self.cdata(), + tcx: self.tcx(), from_id_range: id_range, to_id_range: id_range, last_filemap_index: 0 } } +} - pub fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> { - self.tcx.expect("missing TyCtxt in DecodeContext") +impl<'a, 'tcx> Metadata<'a, 'tcx> for &'a MetadataBlob { + fn raw_bytes(self) -> &'a [u8] { + match *self { + MetadataBlob::Inflated(ref vec) => &vec[..], + MetadataBlob::Archive(ref ar) => ar.as_slice(), + } } +} - pub fn cdata(&self) -> &'a CrateMetadata { - self.cdata.expect("missing CrateMetadata in DecodeContext") - } +impl<'a, 'tcx> Metadata<'a, 'tcx> for &'a CrateMetadata { + fn raw_bytes(self) -> &'a [u8] { self.blob.raw_bytes() } + fn cdata(self) -> Option<&'a CrateMetadata> { Some(self) } +} + +impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadata, TyCtxt<'a, 'tcx, 'tcx>) { + fn raw_bytes(self) -> &'a [u8] { self.0.raw_bytes() } + fn cdata(self) -> Option<&'a CrateMetadata> { Some(self.0) } + fn tcx(self) -> Option> { Some(self.1) } +} - pub fn decode(&mut self) -> T { - T::decode(self).unwrap() +// HACK(eddyb) Only used by astencode to customize the from/to IdRange's. +impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadata, TyCtxt<'a, 'tcx, 'tcx>, [IdRange; 2]) { + fn raw_bytes(self) -> &'a [u8] { self.0.raw_bytes() } + fn cdata(self) -> Option<&'a CrateMetadata> { Some(self.0) } + fn tcx(self) -> Option> { Some(self.1) } + + fn decoder(self, pos: usize) -> DecodeContext<'a, 'tcx> { + let mut dcx = (self.0, self.1).decoder(pos); + dcx.from_id_range = self.2[0]; + dcx.to_id_range = self.2[1]; + dcx } +} - pub fn typed(mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Self { - self.tcx = Some(tcx); - self +impl<'a, 'tcx: 'a, T: Decodable> Lazy { + pub fn decode>(self, meta: M) -> T { + T::decode(&mut meta.decoder(self.position)).unwrap() } +} - /// Iterate over the indices of a sequence. - /// This will work solely because of `serialize::opaque`'s - /// simple encoding of `n: usize` followed by `n` elements. - pub fn seq(mut self) -> impl Iterator { - (0..self.read_usize().unwrap()).map(move |_| { - self.decode() +impl<'a, 'tcx: 'a, T: Decodable> LazySeq { + pub fn decode>(self, meta: M) -> impl Iterator + 'a { + let mut dcx = meta.decoder(self.position); + (0..self.len).map(move |_| { + T::decode(&mut dcx).unwrap() }) } } +impl<'a, 'tcx> DecodeContext<'a, 'tcx> { + pub fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> { + self.tcx.expect("missing TyCtxt in DecodeContext") + } + + pub fn cdata(&self) -> &'a CrateMetadata { + self.cdata.expect("missing CrateMetadata in DecodeContext") + } + + fn with_position R, R>(&mut self, pos: usize, f: F) -> R { + let new = opaque::Decoder::new(self.opaque.data, pos); + let old = mem::replace(&mut self.opaque, new); + let r = f(self); + self.opaque = old; + r + } +} + macro_rules! decoder_methods { ($($name:ident -> $ty:ty;)*) => { $(fn $name(&mut self) -> Result<$ty, Self::Error> { @@ -139,6 +183,19 @@ impl<'doc, 'tcx> Decoder for DecodeContext<'doc, 'tcx> { } } +impl<'a, 'tcx, T> SpecializedDecoder> for DecodeContext<'a, 'tcx> { + fn specialized_decode(&mut self) -> Result, Self::Error> { + Ok(Lazy::with_position(self.read_usize()?)) + } +} + +impl<'a, 'tcx, T> SpecializedDecoder> for DecodeContext<'a, 'tcx> { + fn specialized_decode(&mut self) -> Result, Self::Error> { + let len = self.read_usize()?; + Ok(LazySeq::with_position_and_length(self.read_usize()?, len)) + } +} + impl<'a, 'tcx> SpecializedDecoder for DecodeContext<'a, 'tcx> { fn specialized_decode(&mut self) -> Result { let id = u32::decode(self)?; @@ -252,15 +309,33 @@ impl<'a, 'tcx> SpecializedDecoder> for DecodeContext<'a, 'tcx> { return Ok(ty); } - let new = opaque::Decoder::new(self.opaque.data, key.pos); - let old = mem::replace(&mut self.opaque, new); - let ty = Ty::decode(self)?; - self.opaque = old; + let ty = self.with_position(key.pos, Ty::decode)?; tcx.rcache.borrow_mut().insert(key, ty); - return Ok(ty); + Ok(ty) + } else { + Ok(tcx.mk_ty(ty::TypeVariants::decode(self)?)) } + } +} + + +impl<'a, 'tcx> SpecializedDecoder> for DecodeContext<'a, 'tcx> { + fn specialized_decode(&mut self) -> Result, Self::Error> { + Ok(ty::GenericPredicates { + parent: Decodable::decode(self)?, + predicates: (0..self.read_usize()?).map(|_| { + // Handle shorthands first, if we have an usize > 0x80. + if self.opaque.data[self.opaque.position()] & 0x80 != 0 { + let pos = self.read_usize()?; + assert!(pos >= SHORTHAND_OFFSET); + let pos = pos - SHORTHAND_OFFSET; - Ok(tcx.mk_ty(ty::TypeVariants::decode(self)?)) + self.with_position(pos, ty::Predicate::decode) + } else { + ty::Predicate::decode(self) + } + }).collect()? + }) } } @@ -295,185 +370,110 @@ impl<'a, 'tcx> SpecializedDecoder> for DecodeContext<'a, 'tcx> } } -#[derive(Clone)] -pub struct CrateDep { - pub cnum: CrateNum, - pub name: String, - pub hash: Svh, - pub explicitly_linked: bool, -} - impl<'a, 'tcx> MetadataBlob { - fn root(&self) -> rbml::Doc { - rbml::Doc::new(self.as_slice()) - } - - fn child_at(&'a self, pos: usize, tag: usize) -> DecodeContext<'a, 'tcx> { - DecodeContext::new(rbml::Doc::at(self.as_slice(), pos).child(tag), None) + pub fn is_compatible(&self) -> bool { + self.raw_bytes().starts_with(METADATA_HEADER) } - fn get(&'a self, tag: usize) -> DecodeContext<'a, 'tcx> { - DecodeContext::new(self.root().child(tag), None) + pub fn get_root(&self) -> CrateRoot { + let slice = self.raw_bytes(); + let offset = METADATA_HEADER.len(); + let pos = (((slice[offset + 0] as u32) << 24) | + ((slice[offset + 1] as u32) << 16) | + ((slice[offset + 2] as u32) << 8) | + ((slice[offset + 3] as u32) << 0)) as usize; + Lazy::with_position(pos).decode(self) } - pub fn load_index(&self) -> index::Index { - index::Index::from_rbml(self.root().child(root_tag::index)) - } - - pub fn crate_rustc_version(&self) -> Option { - self.root().maybe_child(root_tag::rustc_version).map(|s| { - str::from_utf8(&s.data[s.start..s.end]).unwrap().to_string() - }) - } - - // Go through each item in the metadata and create a map from that - // item's def-key to the item's DefIndex. - pub fn load_key_map(&self) -> FnvHashMap { - self.load_index().iter_enumerated(self.as_slice()).map(|(index, pos)| { - (self.child_at(pos as usize, item_tag::def_key).decode(), index) - }).collect() - } - - pub fn get_crate_deps(&self) -> Vec { - let dcx = self.get(root_tag::crate_deps); - - dcx.seq().enumerate().map(|(crate_num, (name, hash, explicitly_linked))| { - CrateDep { - cnum: CrateNum::new(crate_num + 1), - name: name, - hash: hash, - explicitly_linked: explicitly_linked, - } + /// Go through each item in the metadata and create a map from that + /// item's def-key to the item's DefIndex. + pub fn load_key_map(&self, index: LazySeq) -> FnvHashMap { + index.iter_enumerated(self.raw_bytes()).map(|(index, item)| { + (item.decode(self).def_key.decode(self), index) }).collect() } - pub fn get_crate_info(&self) -> CrateInfo { - self.get(root_tag::crate_info).decode() - } - pub fn list_crate_metadata(&self, out: &mut io::Write) -> io::Result<()> { write!(out, "=External Dependencies=\n")?; - for dep in &self.get_crate_deps() { - write!(out, "{} {}-{}\n", dep.cnum, dep.name, dep.hash)?; + let root = self.get_root(); + for (i, dep) in root.crate_deps.decode(self).enumerate() { + write!(out, "{} {}-{}\n", i + 1, dep.name, dep.hash)?; } write!(out, "\n")?; Ok(()) } - - pub fn get_imported_filemaps(&self) -> Vec { - self.get(root_tag::codemap).decode() - } - - pub fn each_exported_macro(&self, mut f: F) where - F: FnMut(ast::Name, Vec, Span, String) -> bool, - { - for (name, attrs, span, body) in self.get(root_tag::macro_defs).seq() { - if !f(name, attrs, span, body) { - break; - } - } - } } -impl Family { +impl<'tcx> EntryKind<'tcx> { fn to_def(&self, did: DefId) -> Option { Some(match *self { - Family::Const => Def::Const(did), - Family::AssociatedConst => Def::AssociatedConst(did), - Family::ImmStatic | Family::ForeignImmStatic => Def::Static(did, false), - Family::MutStatic | Family::ForeignMutStatic => Def::Static(did, true), - Family::Struct => Def::Struct(did), - Family::Union => Def::Union(did), - Family::Fn | Family::ForeignFn => Def::Fn(did), - Family::Method => Def::Method(did), - Family::Type => Def::TyAlias(did), - Family::AssociatedType => Def::AssociatedTy(did), - Family::Mod => Def::Mod(did), - Family::Variant => Def::Variant(did), - Family::Trait => Def::Trait(did), - Family::Enum => Def::Enum(did), - - Family::ForeignMod | - Family::Impl | - Family::DefaultImpl | - Family::Field | - Family::Closure => { + EntryKind::Const => Def::Const(did), + EntryKind::AssociatedConst(_) => Def::AssociatedConst(did), + EntryKind::ImmStatic | + EntryKind::ForeignImmStatic => Def::Static(did, false), + EntryKind::MutStatic | + EntryKind::ForeignMutStatic => Def::Static(did, true), + EntryKind::Struct(_) => Def::Struct(did), + EntryKind::Union(_) => Def::Union(did), + EntryKind::Fn(_) | + EntryKind::ForeignFn(_) => Def::Fn(did), + EntryKind::Method(_) => Def::Method(did), + EntryKind::Type => Def::TyAlias(did), + EntryKind::AssociatedType(_) => Def::AssociatedTy(did), + EntryKind::Mod(_) => Def::Mod(did), + EntryKind::Variant(_) => Def::Variant(did), + EntryKind::Trait(_) => Def::Trait(did), + EntryKind::Enum => Def::Enum(did), + + EntryKind::ForeignMod | + EntryKind::Impl(_) | + EntryKind::DefaultImpl(_) | + EntryKind::Field | + EntryKind::Closure (_) => { return None } }) } } -impl<'a, 'tcx> CrateMetadata { - fn maybe_get(&'a self, item: rbml::Doc<'a>, tag: usize) - -> Option> { - item.maybe_child(tag).map(|child| { - DecodeContext::new(child, Some(self)) - }) - } - - fn get(&'a self, item: rbml::Doc<'a>, tag: usize) -> DecodeContext<'a, 'tcx> { - match self.maybe_get(item, tag) { - Some(dcx) => dcx, - None => bug!("failed to find child with tag {}", tag) +fn def_key_name(def_key: &hir_map::DefKey) -> Option { + match def_key.disambiguated_data.data { + DefPathData::TypeNs(ref name) | + DefPathData::ValueNs(ref name) | + DefPathData::Module(ref name) | + DefPathData::MacroDef(ref name) | + DefPathData::TypeParam(ref name) | + DefPathData::LifetimeDef(ref name) | + DefPathData::EnumVariant(ref name) | + DefPathData::Field(ref name) | + DefPathData::Binding(ref name) => { + Some(token::intern(name)) } - } - - fn item_family(&self, item: rbml::Doc) -> Family { - self.get(item, item_tag::family).decode() - } - fn item_visibility(&self, item: rbml::Doc) -> ty::Visibility { - self.get(item, item_tag::visibility).decode() - } + DefPathData::InlinedRoot(_) => bug!("unexpected DefPathData"), - fn item_def_key(&self, item: rbml::Doc) -> hir_map::DefKey { - self.get(item, item_tag::def_key).decode() - } - - fn item_name(&self, item: rbml::Doc) -> ast::Name { - self.maybe_item_name(item).expect("no item in item_name") - } - - fn maybe_item_name(&self, item: rbml::Doc) -> Option { - let name = match self.item_def_key(item).disambiguated_data.data { - DefPathData::TypeNs(name) | - DefPathData::ValueNs(name) | - DefPathData::Module(name) | - DefPathData::MacroDef(name) | - DefPathData::TypeParam(name) | - DefPathData::LifetimeDef(name) | - DefPathData::EnumVariant(name) | - DefPathData::Field(name) | - DefPathData::Binding(name) => Some(name), - - DefPathData::InlinedRoot(_) => bug!("unexpected DefPathData"), - - DefPathData::CrateRoot | - DefPathData::Misc | - DefPathData::Impl | - DefPathData::ClosureExpr | - DefPathData::StructCtor | - DefPathData::Initializer | - DefPathData::ImplTrait => None - }; - - name.map(|s| token::intern(&s)) + DefPathData::CrateRoot | + DefPathData::Misc | + DefPathData::Impl | + DefPathData::ClosureExpr | + DefPathData::StructCtor | + DefPathData::Initializer | + DefPathData::ImplTrait => None } +} - fn maybe_entry(&self, item_id: DefIndex) -> Option { - self.index.lookup_item(self.data.as_slice(), item_id).map(|pos| { - rbml::Doc::at(self.data.as_slice(), pos as usize) - }) +impl<'a, 'tcx> CrateMetadata { + fn maybe_entry(&self, item_id: DefIndex) -> Option>> { + self.root.index.lookup(self.blob.raw_bytes(), item_id) } - fn entry(&self, item_id: DefIndex) -> rbml::Doc { + fn entry(&self, item_id: DefIndex) -> Entry<'tcx> { match self.maybe_entry(item_id) { None => bug!("entry: id not found: {:?} in crate {:?} with number {}", item_id, self.name, self.cnum), - Some(d) => d + Some(d) => d.decode(self) } } @@ -484,62 +484,42 @@ impl<'a, 'tcx> CrateMetadata { } } - fn entry_data(&self, doc: rbml::Doc) -> EntryData { - self.get(doc, item_tag::data).decode() - } - - fn entry_typed_data(&self, doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>) - -> EntryTypedData<'tcx> { - self.get(doc, item_tag::typed_data).typed(tcx).decode() - } - - fn item_parent_item(&self, d: rbml::Doc) -> Option { - self.item_def_key(d).parent.map(|index| self.local_def_id(index)) - } - - fn doc_type(&self, doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx> { - self.maybe_doc_type(doc, tcx).expect("missing item_tag::ty") - } - - fn maybe_doc_type(&self, doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option> { - self.maybe_get(doc, item_tag::ty).map(|dcx| dcx.typed(tcx).decode()) + fn item_name(&self, item: &Entry<'tcx>) -> ast::Name { + def_key_name(&item.def_key.decode(self)).expect("no name in item_name") } pub fn get_def(&self, index: DefIndex) -> Option { - self.item_family(self.entry(index)).to_def(self.local_def_id(index)) + self.entry(index).kind.to_def(self.local_def_id(index)) } pub fn get_trait_def(&self, item_id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ty::TraitDef<'tcx> { - let item_doc = self.entry(item_id); - let generics = self.doc_generics(item_doc, tcx); - - let data = match self.entry_data(item_doc) { - EntryData::Trait(data) => data, - _ => bug!() - }; - let typed_data = match self.entry_typed_data(item_doc, tcx) { - EntryTypedData::Trait(data) => data, + let data = match self.entry(item_id).kind { + EntryKind::Trait(data) => data.decode(self), _ => bug!() }; - ty::TraitDef::new(data.unsafety, data.paren_sugar, generics, typed_data.trait_ref, - self.def_path(item_id).unwrap().deterministic_hash(tcx))) + ty::TraitDef::new(data.unsafety, data.paren_sugar, + tcx.lookup_generics(self.local_def_id(item_id)), + data.trait_ref.decode((self, tcx)), + self.def_path(item_id).unwrap().deterministic_hash(tcx)) } - fn get_variant(&self, item: rbml::Doc, index: DefIndex) - -> (ty::VariantDefData<'tcx, 'tcx>, Option) { - let data = match self.entry_data(item) { - EntryData::Variant(data) => data, + fn get_variant(&self, item: &Entry<'tcx>, index: DefIndex) + -> (ty::VariantDefData<'tcx, 'tcx>, Option) { + let data = match item.kind { + EntryKind::Variant(data) | + EntryKind::Struct(data) | + EntryKind::Union(data) => data.decode(self), _ => bug!() }; - let fields = self.get(item, item_tag::children).seq().map(|index| { + let fields = item.children.decode(self).map(|index| { let f = self.entry(index); ty::FieldDefData::new(self.local_def_id(index), - self.item_name(f), - self.item_visibility(f)) + self.item_name(&f), + f.visibility) }).collect(); (ty::VariantDefData { @@ -553,27 +533,25 @@ impl<'a, 'tcx> CrateMetadata { pub fn get_adt_def(&self, item_id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ty::AdtDefMaster<'tcx> { - let doc = self.entry(item_id); + let item = self.entry(item_id); let did = self.local_def_id(item_id); let mut ctor_index = None; - let family = self.item_family(doc); - let variants = if family == Family::Enum { - self.get(doc, item_tag::children).seq().map(|index| { - let (variant, struct_ctor) = self.get_variant(self.entry(index), index); + let variants = if let EntryKind::Enum = item.kind { + item.children.decode(self).map(|index| { + let (variant, struct_ctor) = self.get_variant(&self.entry(index), index); assert_eq!(struct_ctor, None); variant }).collect() } else{ - let (variant, struct_ctor) = self.get_variant(doc, item_id); + let (variant, struct_ctor) = self.get_variant(&item, item_id); ctor_index = struct_ctor; vec![variant] }; - let kind = match family { - Family::Enum => ty::AdtKind::Enum, - Family::Struct => ty::AdtKind::Struct, - Family::Union => ty::AdtKind::Union, - _ => bug!("get_adt_def called on a non-ADT {:?} - {:?}", - family, did) + let kind = match item.kind { + EntryKind::Enum => ty::AdtKind::Enum, + EntryKind::Struct(_) => ty::AdtKind::Struct, + EntryKind::Union(_) => ty::AdtKind::Union, + _ => bug!("get_adt_def called on a non-ADT {:?}", did) }; let adt = tcx.intern_adt_def(did, kind, variants); @@ -599,42 +577,43 @@ impl<'a, 'tcx> CrateMetadata { pub fn get_predicates(&self, item_id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ty::GenericPredicates<'tcx> { - self.doc_predicates(self.entry(item_id), tcx, item_tag::predicates) + self.entry(item_id).predicates.unwrap().decode((self, tcx)) } pub fn get_super_predicates(&self, item_id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ty::GenericPredicates<'tcx> { - self.doc_predicates(self.entry(item_id), tcx, item_tag::super_predicates) + match self.entry(item_id).kind { + EntryKind::Trait(data) => { + data.decode(self).super_predicates.decode((self, tcx)) + } + _ => bug!() + } } pub fn get_generics(&self, item_id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) - -> &'tcx ty::Generics<'tcx> { - self.doc_generics(self.entry(item_id), tcx) + -> ty::Generics<'tcx> { + self.entry(item_id).generics.unwrap().decode((self, tcx)) } pub fn get_type(&self, id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx> { - self.doc_type(self.entry(id), tcx) + self.entry(id).ty.unwrap().decode((self, tcx)) } pub fn get_stability(&self, id: DefIndex) -> Option { - self.maybe_get(self.entry(id), item_tag::stability).map(|mut dcx| { - dcx.decode() - }) + self.entry(id).stability.map(|stab| stab.decode(self)) } pub fn get_deprecation(&self, id: DefIndex) -> Option { - self.maybe_get(self.entry(id), item_tag::deprecation).map(|mut dcx| { - dcx.decode() - }) + self.entry(id).deprecation.map(|depr| depr.decode(self)) } pub fn get_visibility(&self, id: DefIndex) -> ty::Visibility { - self.item_visibility(self.entry(id)) + self.entry(id).visibility } - fn get_impl_data(&self, id: DefIndex) -> ImplData { - match self.entry_data(self.entry(id)) { - EntryData::Impl(data) => data, + fn get_impl_data(&self, id: DefIndex) -> ImplData<'tcx> { + match self.entry(id).kind { + EntryKind::Impl(data) => data.decode(self), _ => bug!() } } @@ -656,15 +635,12 @@ impl<'a, 'tcx> CrateMetadata { id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option> { - match self.entry_typed_data(self.entry(id), tcx) { - EntryTypedData::Impl(data) => data.trait_ref, - _ => bug!() - } + self.get_impl_data(id).trait_ref.map(|tr| tr.decode((self, tcx))) } /// Iterates over the language items in the given crate. pub fn get_lang_items(&self) -> Vec<(DefIndex, usize)> { - self.get(self.data.root(), root_tag::lang_items).decode() + self.root.lang_items.decode(self).collect() } /// Iterates over each child of the given item. @@ -672,38 +648,34 @@ impl<'a, 'tcx> CrateMetadata { where F: FnMut(def::Export) { // Find the item. - let item_doc = match self.maybe_entry(id) { + let item = match self.maybe_entry(id) { None => return, - Some(item_doc) => item_doc, - }; - - let dcx = match self.maybe_get(item_doc, item_tag::children) { - Some(dcx) => dcx, - None => return + Some(item) => item.decode(self), }; // Iterate over all children. - for child_index in dcx.seq() { + for child_index in item.children.decode(self) { // Get the item. if let Some(child) = self.maybe_entry(child_index) { + let child = child.decode(self); // Hand off the item to the callback. - match self.item_family(child) { + match child.kind { // FIXME(eddyb) Don't encode these in children. - Family::ForeignMod => { - for child_index in self.get(child, item_tag::children).seq() { + EntryKind::ForeignMod => { + for child_index in child.children.decode(self) { callback(def::Export { def_id: self.local_def_id(child_index), - name: self.item_name(self.entry(child_index)) + name: self.item_name(&self.entry(child_index)) }); } continue; } - Family::Impl | Family::DefaultImpl => continue, + EntryKind::Impl(_) | EntryKind::DefaultImpl(_) => continue, _ => {} } - if let Some(name) = self.maybe_item_name(child) { + if let Some(name) = def_key_name(&child.def_key.decode(self)) { callback(def::Export { def_id: self.local_def_id(child_index), name: name @@ -712,17 +684,15 @@ impl<'a, 'tcx> CrateMetadata { } } - let reexports = match self.entry_data(item_doc) { - EntryData::Mod(data) => data.reexports, - _ => return - }; - for exp in reexports { - callback(exp); + if let EntryKind::Mod(data) = item.kind { + for exp in data.decode(self).reexports.decode(self) { + callback(exp); + } } } pub fn maybe_get_item_name(&self, id: DefIndex) -> Option { - self.maybe_item_name(self.entry(id)) + def_key_name(&self.entry(id).def_key.decode(self)) } pub fn maybe_get_item_ast(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefIndex) @@ -733,76 +703,46 @@ impl<'a, 'tcx> CrateMetadata { let parent_def_id = self.local_def_id(self.def_key(id).parent.unwrap()); let mut parent_def_path = self.def_path(id).unwrap(); parent_def_path.data.pop(); - item_doc.maybe_child(item_tag::ast).map(|ast_doc| { - decode_inlined_item(self, tcx, parent_def_path, parent_def_id, ast_doc, item_did) + item_doc.ast.map(|ast| { + let ast = ast.decode(self); + decode_inlined_item(self, tcx, parent_def_path, parent_def_id, ast, item_did) }) } pub fn is_item_mir_available(&self, id: DefIndex) -> bool { - if let Some(item_doc) = self.maybe_entry(id) { - return item_doc.maybe_child(item_tag::mir).is_some(); - } - - false + self.maybe_entry(id).and_then(|item| item.decode(self).mir).is_some() } pub fn maybe_get_item_mir(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefIndex) -> Option> { - self.maybe_get(self.entry(id), item_tag::mir).map(|dcx| { - dcx.typed(tcx).decode() - }) + self.entry(id).mir.map(|mir| mir.decode((self, tcx))) } pub fn get_impl_or_trait_item(&self, id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option> { - let item_doc = self.entry(id); - let family = self.item_family(item_doc); - - match family { - Family::AssociatedConst | - Family::Method | - Family::AssociatedType => {} - - _ => return None - } - - let def_id = self.local_def_id(id); - - let container_id = self.item_parent_item(item_doc).unwrap(); - let container = match self.item_family(self.entry(container_id.index)) { - Family::Trait => TraitContainer(container_id), - _ => ImplContainer(container_id), + let item = self.entry(id); + let parent_and_name = || { + let def_key = item.def_key.decode(self); + (self.local_def_id(def_key.parent.unwrap()), + def_key_name(&def_key).unwrap()) }; - let name = self.item_name(item_doc); - let vis = self.item_visibility(item_doc); - - let (defaultness, has_body) = match self.entry_data(item_doc) { - EntryData::TraitAssociated(data) => { - (hir::Defaultness::Default, data.has_default) - } - EntryData::ImplAssociated(data) => { - (data.defaultness, true) - } - _ => bug!() - }; - - Some(match family { - Family::AssociatedConst => { + Some(match item.kind { + EntryKind::AssociatedConst(container) => { + let (parent, name) = parent_and_name(); ty::ConstTraitItem(Rc::new(ty::AssociatedConst { name: name, - ty: self.doc_type(item_doc, tcx), - vis: vis, - defaultness: defaultness, - def_id: def_id, - container: container, - has_value: has_body, + ty: item.ty.unwrap().decode((self, tcx)), + vis: item.visibility, + defaultness: container.defaultness(), + def_id: self.local_def_id(id), + container: container.with_def_id(parent), + has_value: container.has_body(), })) } - Family::Method => { - let generics = self.doc_generics(item_doc, tcx); - let predicates = self.doc_predicates(item_doc, tcx, item_tag::predicates); - let ity = tcx.lookup_item_type(def_id).ty; + EntryKind::Method(data) => { + let (parent, name) = parent_and_name(); + let ity = item.ty.unwrap().decode((self, tcx)); let fty = match ity.sty { ty::TyFnDef(.., fty) => fty, _ => bug!( @@ -810,49 +750,46 @@ impl<'a, 'tcx> CrateMetadata { ity, name) }; - let explicit_self = match self.entry_typed_data(item_doc, tcx) { - EntryTypedData::Method(data) => data.explicit_self, - _ => bug!() - }; + let data = data.decode(self); ty::MethodTraitItem(Rc::new(ty::Method { name: name, - generics: generics, - predicates: predicates, + generics: tcx.lookup_generics(self.local_def_id(id)), + predicates: item.predicates.unwrap().decode((self, tcx)), fty: fty, - explicit_self: explicit_self, - vis: vis, - defaultness: defaultness, - has_body: has_body, - def_id: def_id, - container: container, + explicit_self: data.explicit_self.decode((self, tcx)), + vis: item.visibility, + defaultness: data.container.defaultness(), + has_body: data.container.has_body(), + def_id: self.local_def_id(id), + container: data.container.with_def_id(parent), })) } - Family::AssociatedType => { + EntryKind::AssociatedType(container) => { + let (parent, name) = parent_and_name(); ty::TypeTraitItem(Rc::new(ty::AssociatedType { name: name, - ty: self.maybe_doc_type(item_doc, tcx), - vis: vis, - defaultness: defaultness, - def_id: def_id, - container: container, + ty: item.ty.map(|ty| ty.decode((self, tcx))), + vis: item.visibility, + defaultness: container.defaultness(), + def_id: self.local_def_id(id), + container: container.with_def_id(parent), })) } - _ => bug!() + _ => return None }) } pub fn get_item_variances(&self, id: DefIndex) -> Vec { - let item_doc = self.entry(id); - self.get(item_doc, item_tag::variances).decode() + self.entry(id).variances.decode(self).collect() } pub fn get_struct_ctor_def_id(&self, node_id: DefIndex) -> Option { - let data = match self.entry_data(self.entry(node_id)) { - EntryData::Variant(data) => data, - _ => bug!() - }; - - data.struct_ctor.map(|index| self.local_def_id(index)) + match self.entry(node_id).kind { + EntryKind::Struct(data) => { + data.decode(self).struct_ctor.map(|index| self.local_def_id(index)) + } + _ => None + } } pub fn get_item_attrs(&self, node_id: DefIndex) -> Vec { @@ -860,30 +797,25 @@ impl<'a, 'tcx> CrateMetadata { // we assume that someone passing in a tuple struct ctor is actually wanting to // look at the definition let mut item = self.entry(node_id); - let def_key = self.item_def_key(item); + let def_key = item.def_key.decode(self); if def_key.disambiguated_data.data == DefPathData::StructCtor { item = self.entry(def_key.parent.unwrap()); } - self.get_attributes(item) + self.get_attributes(&item) } pub fn get_struct_field_names(&self, id: DefIndex) -> Vec { - self.get(self.entry(id), item_tag::children).seq().map(|index| { - self.item_name(self.entry(index)) + self.entry(id).children.decode(self).map(|index| { + self.item_name(&self.entry(index)) }).collect() } - fn get_attributes(&self, md: rbml::Doc) -> Vec { - self.maybe_get(md, item_tag::attributes).map_or(vec![], |mut dcx| { - let mut attrs = dcx.decode::>(); - + fn get_attributes(&self, item: &Entry<'tcx>) -> Vec { + item.attributes.decode(self).map(|mut attr| { // Need new unique IDs: old thread-local IDs won't map to new threads. - for attr in attrs.iter_mut() { - attr.node.id = attr::mk_attr_id(); - } - - attrs - }) + attr.node.id = attr::mk_attr_id(); + attr + }).collect() } // Translate a DefId from the current compilation environment to a DefId @@ -898,106 +830,97 @@ impl<'a, 'tcx> CrateMetadata { None } - pub fn each_inherent_implementation_for_type(&self, id: DefIndex, mut callback: F) - where F: FnMut(DefId), - { - for impl_def_id in self.get(self.entry(id), item_tag::inherent_impls).seq() { - callback(impl_def_id); - } + pub fn get_inherent_implementations_for_type(&self, id: DefIndex) -> Vec { + self.entry(id).inherent_impls.decode(self).map(|index| { + self.local_def_id(index) + }).collect() } - pub fn each_implementation_for_trait(&self, - filter: Option, - mut callback: F) where - F: FnMut(DefId), - { + pub fn get_implementations_for_trait(&self, filter: Option, result: &mut Vec) { // Do a reverse lookup beforehand to avoid touching the crate_num // hash map in the loop below. let filter = match filter.map(|def_id| self.reverse_translate_def_id(def_id)) { - Some(Some(def_id)) => Some(def_id), + Some(Some(def_id)) => Some((def_id.krate.as_u32(), def_id.index)), Some(None) => return, None => None }; // FIXME(eddyb) Make this O(1) instead of O(n). - for trait_doc in self.data.root().children_of(root_tag::impls) { - let mut dcx = DecodeContext::new(trait_doc, Some(self)); - - let (krate, index) = dcx.decode(); - if let Some(local_did) = filter { - if (local_did.krate.as_u32(), local_did.index) != (krate, index) { - continue; - } + for trait_impls in self.root.impls.decode(self) { + if filter.is_some() && filter != Some(trait_impls.trait_id) { + continue; } - for impl_def_id in dcx.seq() { - callback(impl_def_id); + result.extend(trait_impls.impls.decode(self).map(|index| { + self.local_def_id(index) + })); + + if filter.is_some() { + break; } } } pub fn get_trait_of_item(&self, id: DefIndex) -> Option { - let item_doc = self.entry(id); - let parent_item_id = match self.item_parent_item(item_doc) { - None => return None, - Some(item_id) => item_id, - }; - match self.item_family(self.entry(parent_item_id.index)) { - Family::Trait => Some(parent_item_id), - _ => None - } + self.entry(id).def_key.decode(self).parent.and_then(|parent_index| { + match self.entry(parent_index).kind { + EntryKind::Trait(_) => Some(self.local_def_id(parent_index)), + _ => None + } + }) } pub fn get_native_libraries(&self) -> Vec<(NativeLibraryKind, String)> { - self.get(self.data.root(), root_tag::native_libraries).decode() + self.root.native_libraries.decode(self).collect() } pub fn get_dylib_dependency_formats(&self) -> Vec<(CrateNum, LinkagePreference)> { - let dcx = self.get(self.data.root(), root_tag::dylib_dependency_formats); - - dcx.seq::>().enumerate().flat_map(|(i, link)| { + self.root.dylib_dependency_formats.decode(self).enumerate().flat_map(|(i, link)| { let cnum = CrateNum::new(i + 1); link.map(|link| (self.cnum_map.borrow()[cnum], link)) }).collect() } pub fn get_missing_lang_items(&self) -> Vec { - self.get(self.data.root(), root_tag::lang_items_missing).decode() + self.root.lang_items_missing.decode(self).collect() } - pub fn get_fn_arg_names(&self, id: DefIndex) -> Vec { - self.maybe_get(self.entry(id), item_tag::fn_arg_names) - .map_or(vec![], |mut dcx| dcx.decode()) + pub fn get_fn_arg_names(&self, id: DefIndex) -> Vec { + let arg_names = match self.entry(id).kind { + EntryKind::Fn(data) | + EntryKind::ForeignFn(data) => data.decode(self).arg_names, + EntryKind::Method(data) => data.decode(self).fn_data.arg_names, + _ => LazySeq::empty() + }; + arg_names.decode(self).collect() } pub fn get_reachable_ids(&self) -> Vec { - let dcx = self.get(self.data.root(), root_tag::reachable_ids); - - dcx.seq().map(|index| self.local_def_id(index)).collect() + self.root.reachable_ids.decode(self).map(|index| self.local_def_id(index)).collect() } pub fn is_const_fn(&self, id: DefIndex) -> bool { - let constness = match self.entry_data(self.entry(id)) { - EntryData::ImplAssociated(data) => data.constness, - EntryData::Fn(data) => data.constness, + let constness = match self.entry(id).kind { + EntryKind::Method(data) => data.decode(self).fn_data.constness, + EntryKind::Fn(data) => data.decode(self).constness, _ => hir::Constness::NotConst }; constness == hir::Constness::Const } pub fn is_extern_item(&self, id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> bool { - let item_doc = match self.maybe_entry(id) { - Some(doc) => doc, + let item = match self.maybe_entry(id) { + Some(item) => item.decode(self), None => return false, }; - let applicable = match self.item_family(item_doc) { - Family::ImmStatic | - Family::MutStatic | - Family::ForeignImmStatic | - Family::ForeignMutStatic => true, + let applicable = match item.kind { + EntryKind::ImmStatic | + EntryKind::MutStatic | + EntryKind::ForeignImmStatic | + EntryKind::ForeignMutStatic => true, - Family::Fn | Family::ForeignFn => { + EntryKind::Fn(_) | EntryKind::ForeignFn(_) => { self.get_generics(id, tcx).types.is_empty() } @@ -1006,83 +929,53 @@ impl<'a, 'tcx> CrateMetadata { if applicable { attr::contains_extern_indicator(tcx.sess.diagnostic(), - &self.get_attributes(item_doc)) + &self.get_attributes(&item)) } else { false } } pub fn is_foreign_item(&self, id: DefIndex) -> bool { - match self.item_family(self.entry(id)) { - Family::ForeignImmStatic | - Family::ForeignMutStatic | - Family::ForeignFn => true, + match self.entry(id).kind { + EntryKind::ForeignImmStatic | + EntryKind::ForeignMutStatic | + EntryKind::ForeignFn(_) => true, _ => false } } - fn doc_generics(&self, base_doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>) - -> &'tcx ty::Generics<'tcx> { - let generics = self.get(base_doc, item_tag::generics).typed(tcx).decode(); - tcx.alloc_generics(generics) - } - - fn doc_predicates(&self, base_doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>, tag: usize) - -> ty::GenericPredicates<'tcx> { - let mut dcx = self.get(base_doc, tag).typed(tcx); - - ty::GenericPredicates { - parent: dcx.decode(), - predicates: (0..dcx.decode::()).map(|_| { - // Handle shorthands first, if we have an usize > 0x80. - if dcx.opaque.data[dcx.opaque.position()] & 0x80 != 0 { - let pos = dcx.decode::(); - assert!(pos >= SHORTHAND_OFFSET); - let pos = pos - SHORTHAND_OFFSET; - - let data = self.data.as_slice(); - let doc = rbml::Doc { - data: data, - start: pos, - end: data.len(), - }; - DecodeContext::new(doc, Some(self)).typed(tcx).decode() - } else { - dcx.decode() - } - }).collect() - } - } - pub fn is_defaulted_trait(&self, trait_id: DefIndex) -> bool { - match self.entry_data(self.entry(trait_id)) { - EntryData::Trait(data) => data.has_default_impl, + match self.entry(trait_id).kind { + EntryKind::Trait(data) => data.decode(self).has_default_impl, _ => bug!() } } pub fn is_default_impl(&self, impl_id: DefIndex) -> bool { - self.item_family(self.entry(impl_id)) == Family::DefaultImpl + match self.entry(impl_id).kind { + EntryKind::DefaultImpl(_) => true, + _ => false + } } pub fn closure_kind(&self, closure_id: DefIndex) -> ty::ClosureKind { - match self.entry_data(self.entry(closure_id)) { - EntryData::Closure(data) => data.kind, + match self.entry(closure_id).kind { + EntryKind::Closure(data) => data.decode(self).kind, _ => bug!() } } pub fn closure_ty(&self, closure_id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ty::ClosureTy<'tcx> { - match self.entry_typed_data(self.entry(closure_id), tcx) { - EntryTypedData::Closure(data) => data.ty, + match self.entry(closure_id).kind { + EntryKind::Closure(data) => data.decode(self).ty.decode((self, tcx)), _ => bug!() } } pub fn def_key(&self, id: DefIndex) -> hir_map::DefKey { debug!("def_key: id={:?}", id); - self.item_def_key(self.entry(id)) + self.entry(id).def_key.decode(self) } // Returns the path leading to the thing with this `id`. Note that @@ -1096,4 +989,140 @@ impl<'a, 'tcx> CrateMetadata { None } } + + /// Imports the codemap from an external crate into the codemap of the crate + /// currently being compiled (the "local crate"). + /// + /// The import algorithm works analogous to how AST items are inlined from an + /// external crate's metadata: + /// For every FileMap in the external codemap an 'inline' copy is created in the + /// local codemap. The correspondence relation between external and local + /// FileMaps is recorded in the `ImportedFileMap` objects returned from this + /// function. When an item from an external crate is later inlined into this + /// crate, this correspondence information is used to translate the span + /// information of the inlined item so that it refers the correct positions in + /// the local codemap (see `>`). + /// + /// The import algorithm in the function below will reuse FileMaps already + /// existing in the local codemap. For example, even if the FileMap of some + /// source file of libstd gets imported many times, there will only ever be + /// one FileMap object for the corresponding file in the local codemap. + /// + /// Note that imported FileMaps do not actually contain the source code of the + /// file they represent, just information about length, line breaks, and + /// multibyte characters. This information is enough to generate valid debuginfo + /// for items inlined from other crates. + pub fn imported_filemaps(&'a self, local_codemap: &codemap::CodeMap) + -> Ref<'a, Vec> { + { + let filemaps = self.codemap_import_info.borrow(); + if !filemaps.is_empty() { + return filemaps; + } + } + + let external_codemap = self.root.codemap.decode(self); + + let imported_filemaps = external_codemap.map(|filemap_to_import| { + // Try to find an existing FileMap that can be reused for the filemap to + // be imported. A FileMap is reusable if it is exactly the same, just + // positioned at a different offset within the codemap. + let reusable_filemap = { + local_codemap.files + .borrow() + .iter() + .find(|fm| are_equal_modulo_startpos(&fm, &filemap_to_import)) + .map(|rc| rc.clone()) + }; + + match reusable_filemap { + Some(fm) => { + cstore::ImportedFileMap { + original_start_pos: filemap_to_import.start_pos, + original_end_pos: filemap_to_import.end_pos, + translated_filemap: fm + } + } + None => { + // We can't reuse an existing FileMap, so allocate a new one + // containing the information we need. + let syntax_pos::FileMap { + name, + abs_path, + start_pos, + end_pos, + lines, + multibyte_chars, + .. + } = filemap_to_import; + + let source_length = (end_pos - start_pos).to_usize(); + + // Translate line-start positions and multibyte character + // position into frame of reference local to file. + // `CodeMap::new_imported_filemap()` will then translate those + // coordinates to their new global frame of reference when the + // offset of the FileMap is known. + let mut lines = lines.into_inner(); + for pos in &mut lines { + *pos = *pos - start_pos; + } + let mut multibyte_chars = multibyte_chars.into_inner(); + for mbc in &mut multibyte_chars { + mbc.pos = mbc.pos - start_pos; + } + + let local_version = local_codemap.new_imported_filemap(name, + abs_path, + source_length, + lines, + multibyte_chars); + cstore::ImportedFileMap { + original_start_pos: start_pos, + original_end_pos: end_pos, + translated_filemap: local_version + } + } + } + }).collect(); + + // This shouldn't borrow twice, but there is no way to downgrade RefMut to Ref. + *self.codemap_import_info.borrow_mut() = imported_filemaps; + self.codemap_import_info.borrow() + } +} + +fn are_equal_modulo_startpos(fm1: &syntax_pos::FileMap, fm2: &syntax_pos::FileMap) -> bool { + if fm1.name != fm2.name { + return false; + } + + let lines1 = fm1.lines.borrow(); + let lines2 = fm2.lines.borrow(); + + if lines1.len() != lines2.len() { + return false; + } + + for (&line1, &line2) in lines1.iter().zip(lines2.iter()) { + if (line1 - fm1.start_pos) != (line2 - fm2.start_pos) { + return false; + } + } + + let multibytes1 = fm1.multibyte_chars.borrow(); + let multibytes2 = fm2.multibyte_chars.borrow(); + + if multibytes1.len() != multibytes2.len() { + return false; + } + + for (mb1, mb2) in multibytes1.iter().zip(multibytes2.iter()) { + if (mb1.bytes != mb2.bytes) || + ((mb1.pos - fm1.start_pos) != (mb2.pos - fm2.start_pos)) { + return false; + } + } + + true } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index e690e5198795c..185aa9e3b921c 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -8,19 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Metadata encoding - -#![allow(unused_must_use)] // everything is just a MemWriter, can't fail - -use astencode::encode_inlined_item; -use common::*; use cstore; -use index::IndexData; +use index::Index; +use schema::*; -use rustc::middle::cstore::{InlinedItemRef, LinkMeta, LinkagePreference}; +use rustc::middle::cstore::{InlinedItemRef, LinkMeta}; +use rustc::middle::cstore::{LinkagePreference, NativeLibraryKind}; use rustc::hir::def; use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId}; use rustc::middle::dependency_format::Linkage; +use rustc::middle::lang_items; +use rustc::mir; use rustc::traits::specialization_graph; use rustc::ty::{self, Ty, TyCtxt}; @@ -33,13 +31,12 @@ use std::hash::Hash; use std::intrinsics; use std::io::prelude::*; use std::io::Cursor; -use std::ops::{Deref, DerefMut}; use std::rc::Rc; use std::u32; use syntax::ast::{self, CRATE_NODE_ID}; use syntax::attr; use syntax; -use rbml; +use syntax_pos; use rustc::hir::{self, PatKind}; use rustc::hir::intravisit::Visitor; @@ -48,7 +45,7 @@ use rustc::hir::intravisit; use super::index_builder::{FromId, IndexBuilder, Untracked}; pub struct EncodeContext<'a, 'tcx: 'a> { - rbml_w: rbml::writer::Encoder<'a>, + opaque: opaque::Encoder<'a>, pub tcx: TyCtxt<'a, 'tcx, 'tcx>, reexports: &'a def::ExportMap, link_meta: &'a LinkMeta, @@ -60,19 +57,6 @@ pub struct EncodeContext<'a, 'tcx: 'a> { predicate_shorthands: FnvHashMap, usize>, } -impl<'a, 'tcx> Deref for EncodeContext<'a, 'tcx> { - type Target = rbml::writer::Encoder<'a>; - fn deref(&self) -> &Self::Target { - &self.rbml_w - } -} - -impl<'a, 'tcx> DerefMut for EncodeContext<'a, 'tcx> { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.rbml_w - } -} - macro_rules! encoder_methods { ($($name:ident($ty:ty);)*) => { $(fn $name(&mut self, value: $ty) -> Result<(), Self::Error> { @@ -109,27 +93,60 @@ impl<'a, 'tcx> Encoder for EncodeContext<'a, 'tcx> { } } +impl<'a, 'tcx, T> SpecializedEncoder> for EncodeContext<'a, 'tcx> { + fn specialized_encode(&mut self, lazy: &Lazy) -> Result<(), Self::Error> { + self.emit_usize(lazy.position) + } +} + +impl<'a, 'tcx, T> SpecializedEncoder> for EncodeContext<'a, 'tcx> { + fn specialized_encode(&mut self, seq: &LazySeq) -> Result<(), Self::Error> { + self.emit_usize(seq.len)?; + self.emit_usize(seq.position) + } +} + impl<'a, 'tcx> SpecializedEncoder> for EncodeContext<'a, 'tcx> { fn specialized_encode(&mut self, ty: &Ty<'tcx>) -> Result<(), Self::Error> { self.encode_with_shorthand(ty, &ty.sty, |ecx| &mut ecx.type_shorthands) } } +impl<'a, 'tcx> SpecializedEncoder> for EncodeContext<'a, 'tcx> { + fn specialized_encode(&mut self, predicates: &ty::GenericPredicates<'tcx>) + -> Result<(), Self::Error> { + predicates.parent.encode(self)?; + predicates.predicates.len().encode(self)?; + for predicate in &predicates.predicates { + self.encode_with_shorthand(predicate, predicate, |ecx| &mut ecx.predicate_shorthands)? + } + Ok(()) + } +} + impl<'a, 'tcx> EncodeContext<'a, 'tcx> { - fn seq(&mut self, iter: I, mut f: F) - where I: IntoIterator, - I::IntoIter: ExactSizeIterator, - F: FnMut(&mut Self, I::Item) -> T, - T: Encodable { - let iter = iter.into_iter(); - self.emit_seq(iter.len(), move |ecx| { - for (i, elem) in iter.enumerate() { - ecx.emit_seq_elt(i, |ecx| { - f(ecx, elem).encode(ecx) - })?; - } - Ok(()) - }).unwrap(); + pub fn position(&self) -> usize { + self.opaque.position() + } + + pub fn lazy(&mut self, value: &T) -> Lazy { + let pos = self.position(); + value.encode(self).unwrap(); + Lazy::with_position(pos) + } + + fn lazy_seq(&mut self, iter: I) -> LazySeq + where I: IntoIterator, T: Encodable { + let pos = self.position(); + let len = iter.into_iter().map(|value| value.encode(self).unwrap()).count(); + LazySeq::with_position_and_length(pos, len) + } + + fn lazy_seq_ref<'b, I, T>(&mut self, iter: I) -> LazySeq + where I: IntoIterator, T: 'b + Encodable { + let pos = self.position(); + let len = iter.into_iter().map(|value| value.encode(self).unwrap()).count(); + LazySeq::with_position_and_length(pos, len) } /// Encode the given value or a previously cached shorthand. @@ -143,9 +160,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { return self.emit_usize(shorthand); } - let start = self.mark_stable_position(); + let start = self.position(); variant.encode(self)?; - let len = self.mark_stable_position() - start; + let len = self.position() - start; // The shorthand encoding uses the same usize as the // discriminant, with an offset so they can't conflict. @@ -170,60 +187,19 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { /// For every DefId that we create a metadata item for, we include a /// serialized copy of its DefKey, which allows us to recreate a path. - fn encode_def_key(&mut self, def_id: DefId) { - self.start_tag(item_tag::def_key); - self.tcx.map.def_key(def_id).encode(self); - self.end_tag(); - } - - // Item info table encoding - fn encode_family(&mut self, f: Family) { - self.start_tag(item_tag::family); - f.encode(self).unwrap(); - self.end_tag(); - } - - fn encode_item_variances(&mut self, def_id: DefId) { - let v = self.tcx.item_variances(def_id); - self.start_tag(item_tag::variances); - v.encode(self); - self.end_tag(); - } - - fn encode_bounds_and_type_for_item(&mut self, def_id: DefId) { + fn encode_def_key(&mut self, def_id: DefId) -> Lazy { let tcx = self.tcx; - self.encode_bounds_and_type(&tcx.lookup_item_type(def_id), - &tcx.lookup_predicates(def_id)); - } - - fn encode_bounds_and_type(&mut self, - scheme: &ty::TypeScheme<'tcx>, - predicates: &ty::GenericPredicates<'tcx>) { - self.encode_generics(&scheme.generics, &predicates); - self.encode_type(scheme.ty); + self.lazy(&tcx.map.def_key(def_id)) } - fn encode_type(&mut self, typ: Ty<'tcx>) { - self.start_tag(item_tag::ty); - typ.encode(self).unwrap(); - self.end_tag(); + fn encode_item_variances(&mut self, def_id: DefId) -> LazySeq { + let tcx = self.tcx; + self.lazy_seq(tcx.item_variances(def_id).iter().cloned()) } - fn encode_variant(&mut self, variant: ty::VariantDef, - struct_ctor: Option) - -> EntryData { - self.start_tag(item_tag::children); - self.seq(&variant.fields, |_, f| { - assert!(f.did.is_local()); - f.did.index - }); - self.end_tag(); - - EntryData::Variant(VariantData { - kind: variant.kind, - disr: variant.disr_val.to_u64_unchecked(), - struct_ctor: struct_ctor - }) + fn encode_item_type(&mut self, def_id: DefId) -> Lazy> { + let tcx = self.tcx; + self.lazy(&tcx.lookup_item_type(def_id).ty) } /// Encode data for the given variant of the given ADT. The @@ -233,97 +209,104 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { /// e.g., the length of the various vectors). fn encode_enum_variant_info(&mut self, (enum_did, Untracked(index)): - (DefId, Untracked)) { + (DefId, Untracked)) -> Entry<'tcx> { let tcx = self.tcx; let def = tcx.lookup_adt_def(enum_did); let variant = &def.variants[index]; - let vid = variant.did; - self.encode_def_key(vid); - self.encode_family(Family::Variant); + let def_id = variant.did; + + let data = VariantData { + kind: variant.kind, + disr: variant.disr_val.to_u64_unchecked(), + struct_ctor: None + }; let enum_id = tcx.map.as_local_node_id(enum_did).unwrap(); let enum_vis = &tcx.map.expect_item(enum_id).vis; - self.encode_visibility(enum_vis); - - let attrs = tcx.get_attrs(vid); - self.encode_attributes(&attrs); - self.encode_stability(vid); - - let data = self.encode_variant(variant, None); - - self.start_tag(item_tag::data); - data.encode(self).unwrap(); - self.end_tag(); - self.start_tag(item_tag::typed_data); - EntryTypedData::Other.encode(self).unwrap(); - self.end_tag(); - - self.encode_bounds_and_type_for_item(vid); + Entry { + kind: EntryKind::Variant(self.lazy(&data)), + visibility: enum_vis.simplify(), + def_key: self.encode_def_key(def_id), + attributes: self.encode_attributes(&tcx.get_attrs(def_id)), + children: self.lazy_seq(variant.fields.iter().map(|f| { + assert!(f.did.is_local()); + f.did.index + })), + stability: self.encode_stability(def_id), + deprecation: self.encode_deprecation(def_id), + + ty: Some(self.encode_item_type(def_id)), + inherent_impls: LazySeq::empty(), + variances: LazySeq::empty(), + generics: Some(self.encode_generics(def_id)), + predicates: Some(self.encode_predicates(def_id)), + + ast: None, + mir: None + } } fn encode_info_for_mod(&mut self, FromId(id, (md, attrs, vis)): - FromId<(&hir::Mod, &[ast::Attribute], &hir::Visibility)>) { + FromId<(&hir::Mod, &[ast::Attribute], &hir::Visibility)>) + -> Entry<'tcx> { let tcx = self.tcx; - let def_id = tcx.map.local_def_id(id); - self.encode_def_key(def_id); - self.encode_family(Family::Mod); - self.encode_visibility(vis); - self.encode_stability(def_id); - self.encode_attributes(attrs); - debug!("(encoding info for module) encoding info for module ID {}", id); - - // Encode info about all the module children. - self.start_tag(item_tag::children); - self.seq(&md.item_ids, |_, item_id| { - tcx.map.local_def_id(item_id.id).index - }); - self.end_tag(); - // Encode the reexports of this module, if this module is public. - let reexports = match self.reexports.get(&id) { - Some(exports) if *vis == hir::Public => exports.clone(), - _ => vec![] + let data = ModData { + reexports: match self.reexports.get(&id) { + Some(exports) if *vis == hir::Public => { + self.lazy_seq_ref(exports) + } + _ => LazySeq::empty() + } }; - self.start_tag(item_tag::data); - EntryData::Mod(ModData { - reexports: reexports - }).encode(self).unwrap(); - self.end_tag(); - - self.start_tag(item_tag::typed_data); - EntryTypedData::Other.encode(self).unwrap(); - self.end_tag(); - } - - fn encode_visibility(&mut self, visibility: T) { - let vis = if visibility.is_public() { - ty::Visibility::Public - } else { - ty::Visibility::PrivateExternal - }; - self.start_tag(item_tag::visibility); - vis.encode(self).unwrap(); - self.end_tag(); + Entry { + kind: EntryKind::Mod(self.lazy(&data)), + visibility: vis.simplify(), + def_key: self.encode_def_key(def_id), + attributes: self.encode_attributes(attrs), + children: self.lazy_seq(md.item_ids.iter().map(|item_id| { + tcx.map.local_def_id(item_id.id).index + })), + stability: self.encode_stability(def_id), + deprecation: self.encode_deprecation(def_id), + + ty: None, + inherent_impls: LazySeq::empty(), + variances: LazySeq::empty(), + generics: None, + predicates: None, + + ast: None, + mir: None + } } } -trait HasVisibility: Sized { - fn is_public(self) -> bool; +trait Visibility { + fn simplify(&self) -> ty::Visibility; } -impl<'a> HasVisibility for &'a hir::Visibility { - fn is_public(self) -> bool { - *self == hir::Public +impl Visibility for hir::Visibility { + fn simplify(&self) -> ty::Visibility { + if *self == hir::Public { + ty::Visibility::Public + } else { + ty::Visibility::PrivateExternal + } } } -impl HasVisibility for ty::Visibility { - fn is_public(self) -> bool { - self == ty::Visibility::Public +impl Visibility for ty::Visibility { + fn simplify(&self) -> ty::Visibility { + if *self == ty::Visibility::Public { + ty::Visibility::Public + } else { + ty::Visibility::PrivateExternal + } } } @@ -350,312 +333,292 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { /// vectors). fn encode_field(&mut self, (adt_def_id, Untracked((variant_index, field_index))): - (DefId, Untracked<(usize, usize)>)) { + (DefId, Untracked<(usize, usize)>)) -> Entry<'tcx> { let tcx = self.tcx; - let def = tcx.lookup_adt_def(adt_def_id); - let variant = &def.variants[variant_index]; + let variant = &tcx.lookup_adt_def(adt_def_id).variants[variant_index]; let field = &variant.fields[field_index]; - let nm = field.name; - debug!("encode_field: encoding {} {:?}", nm, field.did); - - self.encode_family(Family::Field); - self.encode_visibility(field.vis); - self.encode_bounds_and_type_for_item(field.did); - self.encode_def_key(field.did); - + let def_id = field.did; let variant_id = tcx.map.as_local_node_id(variant.did).unwrap(); let variant_data = tcx.map.expect_variant_data(variant_id); - self.encode_attributes(&variant_data.fields()[field_index].attrs); - self.encode_stability(field.did); + + Entry { + kind: EntryKind::Field, + visibility: field.vis.simplify(), + def_key: self.encode_def_key(def_id), + attributes: self.encode_attributes(&variant_data.fields()[field_index].attrs), + children: LazySeq::empty(), + stability: self.encode_stability(def_id), + deprecation: self.encode_deprecation(def_id), + + ty: Some(self.encode_item_type(def_id)), + inherent_impls: LazySeq::empty(), + variances: LazySeq::empty(), + generics: Some(self.encode_generics(def_id)), + predicates: Some(self.encode_predicates(def_id)), + + ast: None, + mir: None + } } - fn encode_struct_ctor(&mut self, ctor_def_id: DefId) { - self.encode_def_key(ctor_def_id); - self.encode_family(Family::Struct); - self.encode_visibility(ty::Visibility::Public); - self.encode_bounds_and_type_for_item(ctor_def_id); + fn encode_struct_ctor(&mut self, (adt_def_id, def_id): (DefId, DefId)) + -> Entry<'tcx> { + let variant = self.tcx.lookup_adt_def(adt_def_id).struct_variant(); - self.encode_stability(ctor_def_id); + let data = VariantData { + kind: variant.kind, + disr: variant.disr_val.to_u64_unchecked(), + struct_ctor: Some(def_id.index) + }; + + Entry { + kind: EntryKind::Struct(self.lazy(&data)), + visibility: ty::Visibility::Public, + def_key: self.encode_def_key(def_id), + attributes: LazySeq::empty(), + children: LazySeq::empty(), + stability: self.encode_stability(def_id), + deprecation: self.encode_deprecation(def_id), + + ty: Some(self.encode_item_type(def_id)), + inherent_impls: LazySeq::empty(), + variances: LazySeq::empty(), + generics: Some(self.encode_generics(def_id)), + predicates: Some(self.encode_predicates(def_id)), + + ast: None, + mir: None + } } - fn encode_generics(&mut self, - generics: &ty::Generics<'tcx>, - predicates: &ty::GenericPredicates<'tcx>) - { - self.start_tag(item_tag::generics); - generics.encode(self).unwrap(); - self.end_tag(); - self.encode_predicates(predicates, item_tag::predicates); + fn encode_generics(&mut self, def_id: DefId) -> Lazy> { + let tcx = self.tcx; + self.lazy(tcx.lookup_generics(def_id)) } - fn encode_predicates(&mut self, - predicates: &ty::GenericPredicates<'tcx>, - tag: usize) { - self.start_tag(tag); - predicates.parent.encode(self).unwrap(); - self.seq(&predicates.predicates, |ecx, predicate| { - ecx.encode_with_shorthand(predicate, predicate, - |ecx| &mut ecx.predicate_shorthands).unwrap() - }); - self.end_tag(); + fn encode_predicates(&mut self, def_id: DefId) -> Lazy> { + let tcx = self.tcx; + self.lazy(&tcx.lookup_predicates(def_id)) } - fn encode_info_for_trait_item(&mut self, def_id: DefId) { + fn encode_info_for_trait_item(&mut self, def_id: DefId) -> Entry<'tcx> { let tcx = self.tcx; let node_id = tcx.map.as_local_node_id(def_id).unwrap(); let ast_item = tcx.map.expect_trait_item(node_id); let trait_item = tcx.impl_or_trait_item(def_id); - let (family, has_default, typed_data) = match trait_item { - ty::ConstTraitItem(ref associated_const) => { - self.encode_bounds_and_type_for_item(def_id); - let trait_def_id = trait_item.container().id(); - encode_inlined_item(self, - InlinedItemRef::TraitItem(trait_def_id, ast_item)); + let container = |has_body| if has_body { + AssociatedContainer::TraitWithDefault + } else { + AssociatedContainer::TraitRequired + }; - (Family::AssociatedConst, - associated_const.has_value, - EntryTypedData::Other) + let kind = match trait_item { + ty::ConstTraitItem(ref associated_const) => { + EntryKind::AssociatedConst(container(associated_const.has_value)) } ty::MethodTraitItem(ref method_ty) => { - self.encode_bounds_and_type_for_item(def_id); - - (Family::Method, - method_ty.has_body, - EntryTypedData::Method(MethodTypedData { - explicit_self: method_ty.explicit_self - })) + let fn_data = if let hir::MethodTraitItem(ref sig, _) = ast_item.node { + FnData { + constness: hir::Constness::NotConst, + arg_names: self.encode_fn_arg_names(&sig.decl) + } + } else { + bug!() + }; + let data = MethodData { + fn_data: fn_data, + container: container(method_ty.has_body), + explicit_self: self.lazy(&method_ty.explicit_self) + }; + EntryKind::Method(self.lazy(&data)) } - ty::TypeTraitItem(ref associated_type) => { - if let Some(ty) = associated_type.ty { - self.encode_type(ty); - } - - (Family::AssociatedType, false, EntryTypedData::Other) + ty::TypeTraitItem(_) => { + EntryKind::AssociatedType(container(false)) } }; - self.encode_def_key(def_id); - self.encode_family(family); - self.encode_visibility(trait_item.vis()); - - self.encode_stability(def_id); - self.encode_attributes(&ast_item.attrs); - if let hir::MethodTraitItem(ref sig, _) = ast_item.node { - self.encode_fn_arg_names(&sig.decl); - }; - - self.start_tag(item_tag::data); - EntryData::TraitAssociated(TraitAssociatedData { - has_default: has_default - }).encode(self).unwrap(); - self.end_tag(); - - self.start_tag(item_tag::typed_data); - typed_data.encode(self).unwrap(); - self.end_tag(); + Entry { + kind: kind, + visibility: trait_item.vis().simplify(), + def_key: self.encode_def_key(def_id), + attributes: self.encode_attributes(&ast_item.attrs), + children: LazySeq::empty(), + stability: self.encode_stability(def_id), + deprecation: self.encode_deprecation(def_id), + + ty: match trait_item { + ty::ConstTraitItem(_) | + ty::MethodTraitItem(_) => { + Some(self.encode_item_type(def_id)) + } + ty::TypeTraitItem(ref associated_type) => { + associated_type.ty.map(|ty| self.lazy(&ty)) + } + }, + inherent_impls: LazySeq::empty(), + variances: LazySeq::empty(), + generics: Some(self.encode_generics(def_id)), + predicates: Some(self.encode_predicates(def_id)), - self.encode_mir(def_id); + ast: if let ty::ConstTraitItem(_) = trait_item { + let trait_def_id = trait_item.container().id(); + Some(self.encode_inlined_item(InlinedItemRef::TraitItem(trait_def_id, ast_item))) + } else { + None + }, + mir: self.encode_mir(def_id) + } } - fn encode_info_for_impl_item(&mut self, def_id: DefId) { + fn encode_info_for_impl_item(&mut self, def_id: DefId) -> Entry<'tcx> { let node_id = self.tcx.map.as_local_node_id(def_id).unwrap(); let ast_item = self.tcx.map.expect_impl_item(node_id); let impl_item = self.tcx.impl_or_trait_item(def_id); let impl_def_id = impl_item.container().id(); - let (family, typed_data) = match impl_item { - ty::ConstTraitItem(_) => { - self.encode_bounds_and_type_for_item(def_id); - encode_inlined_item(self, - InlinedItemRef::ImplItem(impl_def_id, ast_item)); - self.encode_mir(def_id); + let container = match ast_item.defaultness { + hir::Defaultness::Default => AssociatedContainer::ImplDefault, + hir::Defaultness::Final => AssociatedContainer::ImplFinal + }; - (Family::AssociatedConst, EntryTypedData::Other) + let kind = match impl_item { + ty::ConstTraitItem(_) => { + EntryKind::AssociatedConst(container) } - ty::MethodTraitItem(ref method_type) => { - self.encode_bounds_and_type_for_item(def_id); - - (Family::Method, - EntryTypedData::Method(MethodTypedData { - explicit_self: method_type.explicit_self - })) + ty::MethodTraitItem(ref method_ty) => { + let fn_data = if let hir::ImplItemKind::Method(ref sig, _) = ast_item.node { + FnData { + constness: sig.constness, + arg_names: self.encode_fn_arg_names(&sig.decl) + } + } else { + bug!() + }; + let data = MethodData { + fn_data: fn_data, + container: container, + explicit_self: self.lazy(&method_ty.explicit_self) + }; + EntryKind::Method(self.lazy(&data)) } - ty::TypeTraitItem(ref associated_type) => { - if let Some(ty) = associated_type.ty { - self.encode_type(ty); - } - - (Family::AssociatedType, EntryTypedData::Other) + ty::TypeTraitItem(_) => { + EntryKind::AssociatedType(container) } }; - self.encode_def_key(def_id); - self.encode_family(family); - self.encode_visibility(impl_item.vis()); - self.encode_attributes(&ast_item.attrs); - self.encode_stability(def_id); - - let constness = if let hir::ImplItemKind::Method(ref sig, _) = ast_item.node { - if sig.constness == hir::Constness::Const { - encode_inlined_item( - self, - InlinedItemRef::ImplItem(impl_def_id, ast_item)); - } - + let (ast, mir) = if let ty::ConstTraitItem(_) = impl_item { + (true, true) + } else if let hir::ImplItemKind::Method(ref sig, _) = ast_item.node { let generics = self.tcx.lookup_generics(def_id); let types = generics.parent_types as usize + generics.types.len(); let needs_inline = types > 0 || attr::requests_inline(&ast_item.attrs); - if needs_inline || sig.constness == hir::Constness::Const { - self.encode_mir(def_id); - } - self.encode_fn_arg_names(&sig.decl); - sig.constness + let is_const_fn = sig.constness == hir::Constness::Const; + (is_const_fn, needs_inline || is_const_fn) } else { - hir::Constness::NotConst + (false, false) }; - self.start_tag(item_tag::data); - EntryData::ImplAssociated(ImplAssociatedData { - defaultness: ast_item.defaultness, - constness:constness - }).encode(self).unwrap(); - self.end_tag(); - - self.start_tag(item_tag::typed_data); - typed_data.encode(self).unwrap(); - self.end_tag(); + Entry { + kind: kind, + visibility: impl_item.vis().simplify(), + def_key: self.encode_def_key(def_id), + attributes: self.encode_attributes(&ast_item.attrs), + children: LazySeq::empty(), + stability: self.encode_stability(def_id), + deprecation: self.encode_deprecation(def_id), + + ty: match impl_item { + ty::ConstTraitItem(_) | + ty::MethodTraitItem(_) => { + Some(self.encode_item_type(def_id)) + } + ty::TypeTraitItem(ref associated_type) => { + associated_type.ty.map(|ty| self.lazy(&ty)) + } + }, + inherent_impls: LazySeq::empty(), + variances: LazySeq::empty(), + generics: Some(self.encode_generics(def_id)), + predicates: Some(self.encode_predicates(def_id)), + + ast: if ast { + Some(self.encode_inlined_item(InlinedItemRef::ImplItem(impl_def_id, ast_item))) + } else { + None + }, + mir: if mir { + self.encode_mir(def_id) + } else { + None + } + } } - fn encode_fn_arg_names(&mut self, - decl: &hir::FnDecl) { - self.start_tag(item_tag::fn_arg_names); - - self.seq(&decl.inputs, |_, arg| { + fn encode_fn_arg_names(&mut self, decl: &hir::FnDecl) -> LazySeq { + self.lazy_seq(decl.inputs.iter().map(|arg| { if let PatKind::Binding(_, ref path1, _) = arg.pat.node { path1.node } else { syntax::parse::token::intern("") } - }); - - self.end_tag(); + })) } - fn encode_mir(&mut self, def_id: DefId) { - if let Some(mir) = self.mir_map.map.get(&def_id) { - self.start_tag(item_tag::mir as usize); - mir.encode(self); - self.end_tag(); - } + fn encode_mir(&mut self, def_id: DefId) -> Option>> { + self.mir_map.map.get(&def_id).map(|mir| self.lazy(mir)) } // Encodes the inherent implementations of a structure, enumeration, or trait. - fn encode_inherent_implementations(&mut self, def_id: DefId) { - self.start_tag(item_tag::inherent_impls); + fn encode_inherent_implementations(&mut self, def_id: DefId) -> LazySeq { match self.tcx.inherent_impls.borrow().get(&def_id) { - None => <[DefId]>::encode(&[], self).unwrap(), - Some(implementations) => implementations.encode(self).unwrap() + None => LazySeq::empty(), + Some(implementations) => { + self.lazy_seq(implementations.iter().map(|&def_id| { + assert!(def_id.is_local()); + def_id.index + })) + } } - self.end_tag(); } - fn encode_stability(&mut self, def_id: DefId) { - self.tcx.lookup_stability(def_id).map(|stab| { - self.start_tag(item_tag::stability); - stab.encode(self).unwrap(); - self.end_tag(); - }); - self.tcx.lookup_deprecation(def_id).map(|depr| { - self.start_tag(item_tag::deprecation); - depr.encode(self).unwrap(); - self.end_tag(); - }); + fn encode_stability(&mut self, def_id: DefId) -> Option> { + self.tcx.lookup_stability(def_id).map(|stab| self.lazy(stab)) + } + + fn encode_deprecation(&mut self, def_id: DefId) -> Option> { + self.tcx.lookup_deprecation(def_id).map(|depr| self.lazy(&depr)) } fn encode_info_for_item(&mut self, - (def_id, item): (DefId, &hir::Item)) { + (def_id, item): (DefId, &hir::Item)) -> Entry<'tcx> { let tcx = self.tcx; debug!("encoding info for item at {}", tcx.sess.codemap().span_to_string(item.span)); - let (family, data, typed_data) = match item.node { - hir::ItemStatic(_, m, _) => { - self.encode_bounds_and_type_for_item(def_id); - - if m == hir::MutMutable { - (Family::MutStatic, EntryData::Other, EntryTypedData::Other) - } else { - (Family::ImmStatic, EntryData::Other, EntryTypedData::Other) - } - } - hir::ItemConst(..) => { - self.encode_bounds_and_type_for_item(def_id); - encode_inlined_item(self, InlinedItemRef::Item(def_id, item)); - self.encode_mir(def_id); - - (Family::Const, EntryData::Other, EntryTypedData::Other) - } - hir::ItemFn(ref decl, _, constness, _, ref generics, _) => { - let tps_len = generics.ty_params.len(); - self.encode_bounds_and_type_for_item(def_id); - let needs_inline = tps_len > 0 || attr::requests_inline(&item.attrs); - if constness == hir::Constness::Const { - encode_inlined_item(self, InlinedItemRef::Item(def_id, item)); - } - if needs_inline || constness == hir::Constness::Const { - self.encode_mir(def_id); - } - self.encode_fn_arg_names(&decl); + let kind = match item.node { + hir::ItemStatic(_, hir::MutMutable, _) => EntryKind::MutStatic, + hir::ItemStatic(_, hir::MutImmutable, _) => EntryKind::ImmStatic, + hir::ItemConst(..) => EntryKind::Const, + hir::ItemFn(ref decl, _, constness, ..) => { + let data = FnData { + constness: constness, + arg_names: self.encode_fn_arg_names(&decl) + }; - (Family::Fn, EntryData::Fn(FnData { - constness: constness - }), EntryTypedData::Other) + EntryKind::Fn(self.lazy(&data)) } hir::ItemMod(ref m) => { - self.encode_info_for_mod(FromId(item.id, (m, &item.attrs, &item.vis))); - return; - } - hir::ItemForeignMod(ref fm) => { - // Encode all the items in self module. - self.start_tag(item_tag::children); - self.seq(&fm.items, |_, foreign_item| { - tcx.map.local_def_id(foreign_item.id).index - }); - self.end_tag(); - - (Family::ForeignMod, EntryData::Other, EntryTypedData::Other) - } - hir::ItemTy(..) => { - self.encode_bounds_and_type_for_item(def_id); - - (Family::Type, EntryData::Other, EntryTypedData::Other) - } - hir::ItemEnum(ref enum_definition, _) => { - self.encode_item_variances(def_id); - self.encode_bounds_and_type_for_item(def_id); - - self.start_tag(item_tag::children); - self.seq(&enum_definition.variants, |_, v| { - tcx.map.local_def_id(v.node.data.id()).index - }); - self.end_tag(); - - // Encode inherent implementations for self enumeration. - self.encode_inherent_implementations(def_id); - - (Family::Enum, EntryData::Other, EntryTypedData::Other) + return self.encode_info_for_mod(FromId(item.id, (m, &item.attrs, &item.vis))); } + hir::ItemForeignMod(_) => EntryKind::ForeignMod, + hir::ItemTy(..) => EntryKind::Type, + hir::ItemEnum(..) => EntryKind::Enum, hir::ItemStruct(ref struct_def, _) => { - let def = tcx.lookup_adt_def(def_id); - let variant = def.struct_variant(); - - self.encode_bounds_and_type_for_item(def_id); - - self.encode_item_variances(def_id); + let variant = tcx.lookup_adt_def(def_id).struct_variant(); /* Encode def_ids for each field and method for methods, write all the stuff get_trait_method @@ -665,38 +628,32 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } else { None }; - let data = self.encode_variant(variant, struct_ctor); - - // Encode inherent implementations for self structure. - self.encode_inherent_implementations(def_id); - - (Family::Struct, data, EntryTypedData::Other) + EntryKind::Struct(self.lazy(&VariantData { + kind: variant.kind, + disr: variant.disr_val.to_u64_unchecked(), + struct_ctor: struct_ctor + })) } hir::ItemUnion(..) => { - self.encode_bounds_and_type_for_item(def_id); + let variant = tcx.lookup_adt_def(def_id).struct_variant(); - self.encode_item_variances(def_id); - - /* Encode def_ids for each field and method - for methods, write all the stuff get_trait_method - needs to know*/ - let def = self.tcx.lookup_adt_def(def_id); - let data = self.encode_variant(def.struct_variant(), None); - - // Encode inherent implementations for self union. - self.encode_inherent_implementations(def_id); - - (Family::Union, data, EntryTypedData::Other) + EntryKind::Union(self.lazy(&VariantData { + kind: variant.kind, + disr: variant.disr_val.to_u64_unchecked(), + struct_ctor: None + })) } hir::ItemDefaultImpl(..) => { - (Family::DefaultImpl, EntryData::Other, - EntryTypedData::Impl(ImplTypedData { - trait_ref: tcx.impl_trait_ref(def_id) - })) + let data = ImplData { + polarity: hir::ImplPolarity::Positive, + parent_impl: None, + coerce_unsized_kind: None, + trait_ref: tcx.impl_trait_ref(def_id).map(|trait_ref| self.lazy(&trait_ref)) + }; + + EntryKind::DefaultImpl(self.lazy(&data)) } hir::ItemImpl(_, polarity, ..) => { - self.encode_bounds_and_type_for_item(def_id); - let trait_ref = tcx.impl_trait_ref(def_id); let parent = if let Some(trait_ref) = trait_ref { let trait_def = tcx.lookup_trait_def(trait_ref.def_id); @@ -710,71 +667,146 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { None }; - self.start_tag(item_tag::children); - self.seq(&tcx.impl_or_trait_items(def_id)[..], |_, &def_id| { - assert!(def_id.is_local()); - def_id.index - }); - self.end_tag(); - - (Family::Impl, - EntryData::Impl(ImplData { + let data = ImplData { polarity: polarity, parent_impl: parent, coerce_unsized_kind: tcx.custom_coerce_unsized_kinds.borrow() - .get(&def_id).cloned() - }), - EntryTypedData::Impl(ImplTypedData { - trait_ref: trait_ref - })) + .get(&def_id).cloned(), + trait_ref: trait_ref.map(|trait_ref| self.lazy(&trait_ref)) + }; + + EntryKind::Impl(self.lazy(&data)) } hir::ItemTrait(..) => { - self.encode_item_variances(def_id); let trait_def = tcx.lookup_trait_def(def_id); - let trait_predicates = tcx.lookup_predicates(def_id); - - self.encode_generics(&trait_def.generics, &trait_predicates); - self.encode_predicates(&tcx.lookup_super_predicates(def_id), - item_tag::super_predicates); - - self.start_tag(item_tag::children); - self.seq(&tcx.impl_or_trait_items(def_id)[..], |_, &def_id| { - assert!(def_id.is_local()); - def_id.index - }); - self.end_tag(); - - // Encode inherent implementations for self trait. - self.encode_inherent_implementations(def_id); - - (Family::Trait, - EntryData::Trait(TraitData { + let data = TraitData { unsafety: trait_def.unsafety, paren_sugar: trait_def.paren_sugar, - has_default_impl: tcx.trait_has_default_impl(def_id) - }), - EntryTypedData::Trait(TraitTypedData { - trait_ref: trait_def.trait_ref - })) + has_default_impl: tcx.trait_has_default_impl(def_id), + trait_ref: self.lazy(&trait_def.trait_ref), + super_predicates: self.lazy(&tcx.lookup_super_predicates(def_id)) + }; + + EntryKind::Trait(self.lazy(&data)) } hir::ItemExternCrate(_) | hir::ItemUse(_) => { bug!("cannot encode info for item {:?}", item) } }; - self.encode_family(family); - self.encode_def_key(def_id); - self.encode_visibility(&item.vis); - self.encode_attributes(&item.attrs); - self.encode_stability(def_id); - - self.start_tag(item_tag::data); - data.encode(self).unwrap(); - self.end_tag(); + Entry { + kind: kind, + visibility: item.vis.simplify(), + def_key: self.encode_def_key(def_id), + attributes: self.encode_attributes(&item.attrs), + children: match item.node { + hir::ItemForeignMod(ref fm) => { + self.lazy_seq(fm.items.iter().map(|foreign_item| { + tcx.map.local_def_id(foreign_item.id).index + })) + } + hir::ItemEnum(..) => { + let def = self.tcx.lookup_adt_def(def_id); + self.lazy_seq(def.variants.iter().map(|v| { + assert!(v.did.is_local()); + v.did.index + })) + } + hir::ItemStruct(..) | + hir::ItemUnion(..) => { + let def = self.tcx.lookup_adt_def(def_id); + self.lazy_seq(def.struct_variant().fields.iter().map(|f| { + assert!(f.did.is_local()); + f.did.index + })) + } + hir::ItemImpl(..) | + hir::ItemTrait(..) => { + self.lazy_seq(tcx.impl_or_trait_items(def_id).iter().map(|&def_id| { + assert!(def_id.is_local()); + def_id.index + })) + } + _ => LazySeq::empty() + }, + stability: self.encode_stability(def_id), + deprecation: self.encode_deprecation(def_id), + + ty: match item.node { + hir::ItemStatic(..) | + hir::ItemConst(..) | + hir::ItemFn(..) | + hir::ItemTy(..) | + hir::ItemEnum(..) | + hir::ItemStruct(..) | + hir::ItemUnion(..) | + hir::ItemImpl(..) => { + Some(self.encode_item_type(def_id)) + } + _ => None + }, + inherent_impls: self.encode_inherent_implementations(def_id), + variances: match item.node { + hir::ItemEnum(..) | + hir::ItemStruct(..) | + hir::ItemUnion(..) | + hir::ItemTrait(..) => { + self.encode_item_variances(def_id) + } + _ => LazySeq::empty() + }, + generics: match item.node { + hir::ItemStatic(..) | + hir::ItemConst(..) | + hir::ItemFn(..) | + hir::ItemTy(..) | + hir::ItemEnum(..) | + hir::ItemStruct(..) | + hir::ItemUnion(..) | + hir::ItemImpl(..) | + hir::ItemTrait(..) => { + Some(self.encode_generics(def_id)) + } + _ => None + }, + predicates: match item.node { + hir::ItemStatic(..) | + hir::ItemConst(..) | + hir::ItemFn(..) | + hir::ItemTy(..) | + hir::ItemEnum(..) | + hir::ItemStruct(..) | + hir::ItemUnion(..) | + hir::ItemImpl(..) | + hir::ItemTrait(..) => { + Some(self.encode_predicates(def_id)) + } + _ => None + }, - self.start_tag(item_tag::typed_data); - typed_data.encode(self).unwrap(); - self.end_tag(); + ast: match item.node { + hir::ItemConst(..) | + hir::ItemFn(_, _, hir::Constness::Const, ..) => { + Some(self.encode_inlined_item(InlinedItemRef::Item(def_id, item))) + } + _ => None + }, + mir: match item.node { + hir::ItemConst(..) => { + self.encode_mir(def_id) + } + hir::ItemFn(_, _, constness, _, ref generics, _) => { + let tps_len = generics.ty_params.len(); + let needs_inline = tps_len > 0 || attr::requests_inline(&item.attrs); + if needs_inline || constness == hir::Constness::Const { + self.encode_mir(def_id) + } else { + None + } + } + _ => None + } + } } } @@ -822,7 +854,7 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { let ctor_def_id = self.tcx.map.local_def_id(struct_def.id()); self.record(ctor_def_id, EncodeContext::encode_struct_ctor, - ctor_def_id); + (def_id, ctor_def_id)); } } } @@ -849,35 +881,42 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn encode_info_for_foreign_item(&mut self, - (def_id, nitem): (DefId, &hir::ForeignItem)) { + (def_id, nitem): (DefId, &hir::ForeignItem)) + -> Entry<'tcx> { let tcx = self.tcx; debug!("writing foreign item {}", tcx.node_path_str(nitem.id)); - self.encode_def_key(def_id); - self.encode_visibility(&nitem.vis); - self.encode_bounds_and_type_for_item(def_id); - let family = match nitem.node { + let kind = match nitem.node { hir::ForeignItemFn(ref fndecl, _) => { - self.encode_fn_arg_names(&fndecl); - - Family::ForeignFn + let data = FnData { + constness: hir::Constness::NotConst, + arg_names: self.encode_fn_arg_names(&fndecl) + }; + EntryKind::ForeignFn(self.lazy(&data)) } - hir::ForeignItemStatic(_, true) => Family::ForeignMutStatic, - hir::ForeignItemStatic(_, false) => Family::ForeignImmStatic + hir::ForeignItemStatic(_, true) => EntryKind::ForeignMutStatic, + hir::ForeignItemStatic(_, false) => EntryKind::ForeignImmStatic }; - self.encode_family(family); - - self.start_tag(item_tag::data); - EntryData::Other.encode(self).unwrap(); - self.end_tag(); - self.start_tag(item_tag::typed_data); - EntryTypedData::Other.encode(self).unwrap(); - self.end_tag(); - - self.encode_attributes(&nitem.attrs); - self.encode_stability(def_id); + Entry { + kind: kind, + visibility: nitem.vis.simplify(), + def_key: self.encode_def_key(def_id), + attributes: self.encode_attributes(&nitem.attrs), + children: LazySeq::empty(), + stability: self.encode_stability(def_id), + deprecation: self.encode_deprecation(def_id), + + ty: Some(self.encode_item_type(def_id)), + inherent_impls: LazySeq::empty(), + variances: LazySeq::empty(), + generics: Some(self.encode_generics(def_id)), + predicates: Some(self.encode_predicates(def_id)), + + ast: None, + mir: None + } } } @@ -938,68 +977,73 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { } impl<'a, 'tcx> EncodeContext<'a, 'tcx> { - fn encode_info_for_anon_ty(&mut self, def_id: DefId) { - self.encode_def_key(def_id); - self.encode_bounds_and_type_for_item(def_id); + fn encode_info_for_anon_ty(&mut self, def_id: DefId) -> Entry<'tcx> { + Entry { + kind: EntryKind::Type, + visibility: ty::Visibility::Public, + def_key: self.encode_def_key(def_id), + attributes: LazySeq::empty(), + children: LazySeq::empty(), + stability: None, + deprecation: None, + + ty: Some(self.encode_item_type(def_id)), + inherent_impls: LazySeq::empty(), + variances: LazySeq::empty(), + generics: Some(self.encode_generics(def_id)), + predicates: Some(self.encode_predicates(def_id)), + + ast: None, + mir: None + } } - fn encode_info_for_closure(&mut self, def_id: DefId) { + fn encode_info_for_closure(&mut self, def_id: DefId) -> Entry<'tcx> { let tcx = self.tcx; - self.encode_def_key(def_id); - self.encode_family(Family::Closure); - - self.start_tag(item_tag::data); - EntryData::Closure(ClosureData { - kind: tcx.closure_kind(def_id) - }).encode(self).unwrap(); - self.end_tag(); - - self.start_tag(item_tag::typed_data); - EntryTypedData::Closure(ClosureTypedData { - ty: tcx.tables.borrow().closure_tys[&def_id].clone() - }).encode(self).unwrap(); - self.end_tag(); - - assert!(self.mir_map.map.contains_key(&def_id)); - self.encode_mir(def_id); - } - fn encode_info_for_items(&mut self) -> IndexData { - let krate = self.tcx.map.krate(); - - // FIXME(eddyb) Avoid wrapping the items in a doc. - self.start_tag(0).unwrap(); - - let items = { - let mut index = IndexBuilder::new(self); - index.record(DefId::local(CRATE_DEF_INDEX), - EncodeContext::encode_info_for_mod, - FromId(CRATE_NODE_ID, (&krate.module, &krate.attrs, &hir::Public))); - let mut visitor = EncodeVisitor { - index: index, - }; - krate.visit_all_items(&mut visitor); - visitor.index.into_items() + let data = ClosureData { + kind: tcx.closure_kind(def_id), + ty: self.lazy(&tcx.tables.borrow().closure_tys[&def_id]) }; - self.end_tag(); - - items + Entry { + kind: EntryKind::Closure(self.lazy(&data)), + visibility: ty::Visibility::Public, + def_key: self.encode_def_key(def_id), + attributes: self.encode_attributes(&tcx.get_attrs(def_id)), + children: LazySeq::empty(), + stability: None, + deprecation: None, + + ty: None, + inherent_impls: LazySeq::empty(), + variances: LazySeq::empty(), + generics: None, + predicates: None, + + ast: None, + mir: self.encode_mir(def_id) + } } - fn encode_item_index(&mut self, index: IndexData) { - self.start_tag(root_tag::index); - index.write_index(&mut self.opaque.cursor); - self.end_tag(); + fn encode_info_for_items(&mut self) -> Index { + let krate = self.tcx.map.krate(); + let mut index = IndexBuilder::new(self); + index.record(DefId::local(CRATE_DEF_INDEX), + EncodeContext::encode_info_for_mod, + FromId(CRATE_NODE_ID, (&krate.module, &krate.attrs, &hir::Public))); + let mut visitor = EncodeVisitor { + index: index, + }; + krate.visit_all_items(&mut visitor); + visitor.index.into_items() } - fn encode_attributes(&mut self, attrs: &[ast::Attribute]) { - self.start_tag(item_tag::attributes); - attrs.encode(self).unwrap(); - self.end_tag(); + fn encode_attributes(&mut self, attrs: &[ast::Attribute]) -> LazySeq { + self.lazy_seq_ref(attrs) } - fn encode_crate_deps(&mut self) { + fn encode_crate_deps(&mut self) -> LazySeq { fn get_ordered_deps(cstore: &cstore::CStore) -> Vec<(CrateNum, Rc)> { // Pull the cnums and name,vers,hash out of cstore @@ -1025,96 +1069,71 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { // the assumption that they are numbered 1 to n. // FIXME (#2166): This is not nearly enough to support correct versioning // but is enough to get transitive crate dependencies working. - self.start_tag(root_tag::crate_deps); let deps = get_ordered_deps(self.cstore); - self.seq(&deps, |_, &(_, ref dep)| { - (dep.name(), dep.hash(), dep.explicitly_linked.get()) - }); - self.end_tag(); + self.lazy_seq(deps.iter().map(|&(_, ref dep)| { + CrateDep { + name: syntax::parse::token::intern(dep.name()), + hash: dep.hash(), + explicitly_linked: dep.explicitly_linked.get() + } + })) } - fn encode_lang_items(&mut self) { + fn encode_lang_items(&mut self) + -> (LazySeq<(DefIndex, usize)>, LazySeq) { let tcx = self.tcx; - let lang_items = || { - tcx.lang_items.items().iter().enumerate().filter_map(|(i, &opt_def_id)| { - if let Some(def_id) = opt_def_id { - if def_id.is_local() { - return Some((def_id.index, i)); - } + let lang_items = tcx.lang_items.items().iter(); + (self.lazy_seq(lang_items.enumerate().filter_map(|(i, &opt_def_id)| { + if let Some(def_id) = opt_def_id { + if def_id.is_local() { + return Some((def_id.index, i)); } - None - }) - }; - - let count = lang_items().count(); - let mut lang_items = lang_items(); - - self.start_tag(root_tag::lang_items); - self.seq(0..count, |_, _| lang_items.next().unwrap()); - self.end_tag(); - - self.start_tag(root_tag::lang_items_missing); - tcx.lang_items.missing.encode(self).unwrap(); - self.end_tag(); + } + None + })), self.lazy_seq_ref(&tcx.lang_items.missing)) } - fn encode_native_libraries(&mut self) { + fn encode_native_libraries(&mut self) -> LazySeq<(NativeLibraryKind, String)> { let used_libraries = self.tcx.sess.cstore.used_libraries(); - let libs = || { - used_libraries.iter().filter_map(|&(ref lib, kind)| { - match kind { - cstore::NativeStatic => None, // these libraries are not propagated - cstore::NativeFramework | cstore::NativeUnknown => { - Some((kind, lib)) - } + self.lazy_seq(used_libraries.into_iter().filter_map(|(lib, kind)| { + match kind { + cstore::NativeStatic => None, // these libraries are not propagated + cstore::NativeFramework | cstore::NativeUnknown => { + Some((kind, lib)) } - }) - }; - - let count = libs().count(); - let mut libs = libs(); - - self.start_tag(root_tag::native_libraries); - self.seq(0..count, |_, _| libs.next().unwrap()); - self.end_tag(); + } + })) } - fn encode_codemap(&mut self) { + fn encode_codemap(&mut self) -> LazySeq { let codemap = self.tcx.sess.codemap(); let all_filemaps = codemap.files.borrow(); - let filemaps = || { + self.lazy_seq_ref(all_filemaps.iter().filter(|filemap| { // No need to export empty filemaps, as they can't contain spans // that need translation. // Also no need to re-export imported filemaps, as any downstream // crate will import them from their original source. - all_filemaps.iter().filter(|filemap| { - !filemap.lines.borrow().is_empty() && !filemap.is_imported() - }) - }; - - let count = filemaps().count(); - let mut filemaps = filemaps(); - - self.start_tag(root_tag::codemap); - self.seq(0..count, |_, _| filemaps.next().unwrap()); - self.end_tag(); + !filemap.lines.borrow().is_empty() && !filemap.is_imported() + }).map(|filemap| &**filemap)) } /// Serialize the text of the exported macros - fn encode_macro_defs(&mut self) { + fn encode_macro_defs(&mut self) -> LazySeq { let tcx = self.tcx; - self.start_tag(root_tag::macro_defs); - self.seq(&tcx.map.krate().exported_macros, |_, def| { - let body = ::syntax::print::pprust::tts_to_string(&def.body); - (def.name, &def.attrs, def.span, body) - }); - self.end_tag(); + self.lazy_seq(tcx.map.krate().exported_macros.iter().map(|def| { + MacroDef { + name: def.name, + attrs: def.attrs.to_vec(), + span: def.span, + body: ::syntax::print::pprust::tts_to_string(&def.body) + } + })) } } struct ImplVisitor<'a, 'tcx:'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, - impls: FnvHashMap> + impls: FnvHashMap> } impl<'a, 'tcx, 'v> Visitor<'v> for ImplVisitor<'a, 'tcx> { @@ -1124,7 +1143,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ImplVisitor<'a, 'tcx> { if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_id) { self.impls.entry(trait_ref.def_id) .or_insert(vec![]) - .push(impl_id); + .push(impl_id.index); } } } @@ -1132,22 +1151,21 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ImplVisitor<'a, 'tcx> { impl<'a, 'tcx> EncodeContext<'a, 'tcx> { /// Encodes an index, mapping each trait to its (local) implementations. - fn encode_impls(&mut self) { + fn encode_impls(&mut self) -> LazySeq { let mut visitor = ImplVisitor { tcx: self.tcx, impls: FnvHashMap() }; self.tcx.map.krate().visit_all_items(&mut visitor); - self.start_tag(root_tag::impls); - for (trait_def_id, trait_impls) in visitor.impls { - // FIXME(eddyb) Avoid wrapping the entries in docs. - self.start_tag(0); - (trait_def_id.krate.as_u32(), trait_def_id.index).encode(self).unwrap(); - trait_impls.encode(self).unwrap(); - self.end_tag(); - } - self.end_tag(); + let all_impls: Vec<_> = visitor.impls.into_iter().map(|(trait_def_id, impls)| { + TraitImpls { + trait_id: (trait_def_id.krate.as_u32(), trait_def_id.index), + impls: self.lazy_seq(impls) + } + }).collect(); + + self.lazy_seq(all_impls) } // Encodes all reachable symbols in this crate into the metadata. @@ -1156,20 +1174,16 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { // middle::reachable module but filters out items that either don't have a // symbol associated with them (they weren't translated) or if they're an FFI // definition (as that's not defined in this crate). - fn encode_reachable(&mut self) { - self.start_tag(root_tag::reachable_ids); - + fn encode_reachable(&mut self) -> LazySeq { let reachable = self.reachable; - self.seq(reachable, |ecx, &id| ecx.tcx.map.local_def_id(id).index); - - self.end_tag(); + let tcx = self.tcx; + self.lazy_seq(reachable.iter().map(|&id| tcx.map.local_def_id(id).index)) } - fn encode_dylib_dependency_formats(&mut self) { - self.start_tag(root_tag::dylib_dependency_formats); + fn encode_dylib_dependency_formats(&mut self) -> LazySeq> { match self.tcx.sess.dependency_formats.borrow().get(&config::CrateTypeDylib) { Some(arr) => { - self.seq(arr, |_, slot| { + self.lazy_seq(arr.iter().map(|slot| { match *slot { Linkage::NotLinked | Linkage::IncludedFromDylib => None, @@ -1177,16 +1191,140 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { Linkage::Dynamic => Some(LinkagePreference::RequireDynamic), Linkage::Static => Some(LinkagePreference::RequireStatic), } - }); + })) } - None => { - <[Option]>::encode(&[], self).unwrap(); + None => LazySeq::empty() + } + } + + fn encode_crate_root(&mut self) -> Lazy { + let mut i = self.position(); + let crate_deps = self.encode_crate_deps(); + let dylib_dependency_formats = self.encode_dylib_dependency_formats(); + let dep_bytes = self.position() - i; + + // Encode the language items. + i = self.position(); + let (lang_items, lang_items_missing) = self.encode_lang_items(); + let lang_item_bytes = self.position() - i; + + // Encode the native libraries used + i = self.position(); + let native_libraries = self.encode_native_libraries(); + let native_lib_bytes = self.position() - i; + + // Encode codemap + i = self.position(); + let codemap = self.encode_codemap(); + let codemap_bytes = self.position() - i; + + // Encode macro definitions + i = self.position(); + let macro_defs = self.encode_macro_defs(); + let macro_defs_bytes = self.position() - i; + + // Encode the def IDs of impls, for coherence checking. + i = self.position(); + let impls = self.encode_impls(); + let impl_bytes = self.position() - i; + + // Encode reachability info. + i = self.position(); + let reachable_ids = self.encode_reachable(); + let reachable_bytes = self.position() - i; + + // Encode and index the items. + i = self.position(); + let items = self.encode_info_for_items(); + let item_bytes = self.position() - i; + + i = self.position(); + let index = items.write_index(&mut self.opaque.cursor); + let index_bytes = self.position() - i; + + let tcx = self.tcx; + let link_meta = self.link_meta; + let is_rustc_macro = tcx.sess.crate_types.borrow().contains(&CrateTypeRustcMacro); + let root = self.lazy(&CrateRoot { + rustc_version: RUSTC_VERSION.to_string(), + name: link_meta.crate_name.clone(), + triple: tcx.sess.opts.target_triple.clone(), + hash: link_meta.crate_hash, + disambiguator: tcx.sess.local_crate_disambiguator().to_string(), + panic_strategy: tcx.sess.opts.cg.panic.clone(), + plugin_registrar_fn: tcx.sess.plugin_registrar_fn.get().map(|id| { + tcx.map.local_def_id(id).index + }), + macro_derive_registrar: if is_rustc_macro { + let id = tcx.sess.derive_registrar_fn.get().unwrap(); + Some(tcx.map.local_def_id(id).index) + } else { + None + }, + + index: index, + crate_deps: crate_deps, + dylib_dependency_formats: dylib_dependency_formats, + native_libraries: native_libraries, + lang_items: lang_items, + lang_items_missing: lang_items_missing, + impls: impls, + reachable_ids: reachable_ids, + macro_defs: macro_defs, + codemap: codemap + }); + + let total_bytes = self.position(); + + if self.tcx.sess.meta_stats() { + let mut zero_bytes = 0; + for e in self.opaque.cursor.get_ref() { + if *e == 0 { + zero_bytes += 1; + } } + + println!("metadata stats:"); + println!(" dep bytes: {}", dep_bytes); + println!(" lang item bytes: {}", lang_item_bytes); + println!(" native bytes: {}", native_lib_bytes); + println!(" codemap bytes: {}", codemap_bytes); + println!(" macro def bytes: {}", macro_defs_bytes); + println!(" impl bytes: {}", impl_bytes); + println!(" reachable bytes: {}", reachable_bytes); + println!(" item bytes: {}", item_bytes); + println!(" index bytes: {}", index_bytes); + println!(" zero bytes: {}", zero_bytes); + println!(" total bytes: {}", total_bytes); } - self.end_tag(); + + root } } +// NOTE(eddyb) The following comment was preserved for posterity, even +// though it's no longer relevant as EBML (which uses nested & tagged +// "documents") was replaced with a scheme that can't go out of bounds. +// +// And here we run into yet another obscure archive bug: in which metadata +// loaded from archives may have trailing garbage bytes. Awhile back one of +// our tests was failing sporadically on the OSX 64-bit builders (both nopt +// and opt) by having ebml generate an out-of-bounds panic when looking at +// metadata. +// +// Upon investigation it turned out that the metadata file inside of an rlib +// (and ar archive) was being corrupted. Some compilations would generate a +// metadata file which would end in a few extra bytes, while other +// compilations would not have these extra bytes appended to the end. These +// extra bytes were interpreted by ebml as an extra tag, so they ended up +// being interpreted causing the out-of-bounds. +// +// The root cause of why these extra bytes were appearing was never +// discovered, and in the meantime the solution we're employing is to insert +// the length of the metadata to the start of the metadata. Later on this +// will allow us to slice the metadata to the precise length that we just +// generated regardless of trailing bytes that end up in it. + pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, cstore: &cstore::CStore, reexports: &def::ExportMap, @@ -1194,13 +1332,13 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, reachable: &NodeSet, mir_map: &MirMap<'tcx>) -> Vec { let mut cursor = Cursor::new(vec![]); - cursor.write_all(&[0, 0, 0, 0]).unwrap(); - cursor.write_all(metadata_encoding_version).unwrap(); - // Will be filed with the length after encoding the crate. + cursor.write_all(METADATA_HEADER).unwrap(); + + // Will be filed with the root position after encoding everything. cursor.write_all(&[0, 0, 0, 0]).unwrap(); - encode_metadata_inner(&mut EncodeContext { - rbml_w: rbml::writer::Encoder::new(&mut cursor), + let root = EncodeContext { + opaque: opaque::Encoder::new(&mut cursor), tcx: tcx, reexports: reexports, link_meta: link_meta, @@ -1209,138 +1347,16 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir_map: mir_map, type_shorthands: Default::default(), predicate_shorthands: Default::default() - }); - - // RBML compacts the encoded bytes whenever appropriate, - // so there are some garbages left after the end of the data. - let meta_len = cursor.position() as usize; - cursor.get_mut().truncate(meta_len); - - // And here we run into yet another obscure archive bug: in which metadata - // loaded from archives may have trailing garbage bytes. Awhile back one of - // our tests was failing sporadically on the OSX 64-bit builders (both nopt - // and opt) by having rbml generate an out-of-bounds panic when looking at - // metadata. - // - // Upon investigation it turned out that the metadata file inside of an rlib - // (and ar archive) was being corrupted. Some compilations would generate a - // metadata file which would end in a few extra bytes, while other - // compilations would not have these extra bytes appended to the end. These - // extra bytes were interpreted by rbml as an extra tag, so they ended up - // being interpreted causing the out-of-bounds. - // - // The root cause of why these extra bytes were appearing was never - // discovered, and in the meantime the solution we're employing is to insert - // the length of the metadata to the start of the metadata. Later on this - // will allow us to slice the metadata to the precise length that we just - // generated regardless of trailing bytes that end up in it. - // - // We also need to store the metadata encoding version here, because - // rlibs don't have it. To get older versions of rustc to ignore - // this metadata, there are 4 zero bytes at the start, which are - // treated as a length of 0 by old compilers. - - let meta_start = 8 + ::common::metadata_encoding_version.len(); - let len = meta_len - meta_start; + }.encode_crate_root(); let mut result = cursor.into_inner(); - result[meta_start - 4] = (len >> 24) as u8; - result[meta_start - 3] = (len >> 16) as u8; - result[meta_start - 2] = (len >> 8) as u8; - result[meta_start - 1] = (len >> 0) as u8; - result -} -fn encode_metadata_inner(ecx: &mut EncodeContext) { - ecx.wr_tagged_str(root_tag::rustc_version, &rustc_version()); - - let tcx = ecx.tcx; - let link_meta = ecx.link_meta; - - ecx.start_tag(root_tag::crate_info); - let is_rustc_macro = tcx.sess.crate_types.borrow().contains(&CrateTypeRustcMacro); - CrateInfo { - name: link_meta.crate_name.clone(), - triple: tcx.sess.opts.target_triple.clone(), - hash: link_meta.crate_hash, - disambiguator: tcx.sess.local_crate_disambiguator().to_string(), - panic_strategy: tcx.sess.opts.cg.panic.clone(), - plugin_registrar_fn: tcx.sess.plugin_registrar_fn.get().map(|id| { - tcx.map.local_def_id(id).index - }), - macro_derive_registrar: if is_rustc_macro { - let id = tcx.sess.derive_registrar_fn.get().unwrap(); - Some(tcx.map.local_def_id(id).index) - } else { - None - } - }.encode(ecx).unwrap(); - ecx.end_tag(); - - let mut i = ecx.position(); - ecx.encode_crate_deps(); - ecx.encode_dylib_dependency_formats(); - let dep_bytes = ecx.position() - i; - - // Encode the language items. - i = ecx.position(); - ecx.encode_lang_items(); - let lang_item_bytes = ecx.position() - i; - - // Encode the native libraries used - i = ecx.position(); - ecx.encode_native_libraries(); - let native_lib_bytes = ecx.position() - i; - - // Encode codemap - i = ecx.position(); - ecx.encode_codemap(); - let codemap_bytes = ecx.position() - i; - - // Encode macro definitions - i = ecx.position(); - ecx.encode_macro_defs(); - let macro_defs_bytes = ecx.position() - i; - - // Encode the def IDs of impls, for coherence checking. - i = ecx.position(); - ecx.encode_impls(); - let impl_bytes = ecx.position() - i; - - // Encode reachability info. - i = ecx.position(); - ecx.encode_reachable(); - let reachable_bytes = ecx.position() - i; - - // Encode and index the items. - i = ecx.position(); - let items = ecx.encode_info_for_items(); - let item_bytes = ecx.position() - i; - - i = ecx.position(); - ecx.encode_item_index(items); - let index_bytes = ecx.position() - i; - - let total_bytes = ecx.position(); - - if ecx.tcx.sess.meta_stats() { - let mut zero_bytes = 0; - for e in ecx.opaque.cursor.get_ref() { - if *e == 0 { - zero_bytes += 1; - } - } + // Encode the root position. + let header = METADATA_HEADER.len(); + let pos = root.position; + result[header + 0] = (pos >> 24) as u8; + result[header + 1] = (pos >> 16) as u8; + result[header + 2] = (pos >> 8) as u8; + result[header + 3] = (pos >> 0) as u8; - println!("metadata stats:"); - println!(" dep bytes: {}", dep_bytes); - println!(" lang item bytes: {}", lang_item_bytes); - println!(" native bytes: {}", native_lib_bytes); - println!(" codemap bytes: {}", codemap_bytes); - println!(" macro def bytes: {}", macro_defs_bytes); - println!(" impl bytes: {}", impl_bytes); - println!(" reachable bytes: {}", reachable_bytes); - println!(" item bytes: {}", item_bytes); - println!(" index bytes: {}", index_bytes); - println!(" zero bytes: {}", zero_bytes); - println!(" total bytes: {}", total_bytes); - } + result } diff --git a/src/librustc_metadata/index.rs b/src/librustc_metadata/index.rs index 2c16411c37bdf..ef83251f51e8d 100644 --- a/src/librustc_metadata/index.rs +++ b/src/librustc_metadata/index.rs @@ -8,65 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use schema::*; + use rustc::hir::def_id::{DefId, DefIndex}; -use rbml; use std::io::{Cursor, Write}; use std::slice; use std::u32; -/// As part of the metadata, we generate an index that stores, for -/// each DefIndex, the position of the corresponding RBML document (if -/// any). This is just a big `[u32]` slice, where an entry of -/// `u32::MAX` indicates that there is no RBML document. This little -/// struct just stores the offsets within the metadata of the start -/// and end of this slice. These are actually part of an RBML -/// document, but for looking things up in the metadata, we just -/// discard the RBML positioning and jump directly to the data. -pub struct Index { - data_start: usize, - data_end: usize, -} - -impl Index { - /// Given the RBML doc representing the index, save the offests - /// for later. - pub fn from_rbml(index: rbml::Doc) -> Index { - Index { data_start: index.start, data_end: index.end } - } - - /// Given the metadata, extract out the offset of a particular - /// DefIndex (if any). - #[inline(never)] - pub fn lookup_item(&self, bytes: &[u8], def_index: DefIndex) -> Option { - let words = bytes_to_words(&bytes[self.data_start..self.data_end]); - let index = def_index.as_usize(); - - debug!("lookup_item: index={:?} words.len={:?}", - index, words.len()); - - let position = u32::from_le(words[index]); - if position == u32::MAX { - debug!("lookup_item: position=u32::MAX"); - None - } else { - debug!("lookup_item: position={:?}", position); - Some(position) - } - } - - pub fn iter_enumerated<'a>(&self, bytes: &'a [u8]) - -> impl Iterator + 'a { - let words = bytes_to_words(&bytes[self.data_start..self.data_end]); - words.iter().enumerate().filter_map(|(index, &position)| { - if position == u32::MAX { - None - } else { - Some((DefIndex::new(index), u32::from_le(position))) - } - }) - } -} - /// While we are generating the metadata, we also track the position /// of each DefIndex. It is not required that all definitions appear /// in the metadata, nor that they are serialized in order, and @@ -74,27 +22,27 @@ impl Index { /// `u32::MAX`. Whenever an index is visited, we fill in the /// appropriate spot by calling `record_position`. We should never /// visit the same index twice. -pub struct IndexData { +pub struct Index { positions: Vec, } -impl IndexData { - pub fn new(max_index: usize) -> IndexData { - IndexData { +impl Index { + pub fn new(max_index: usize) -> Index { + Index { positions: vec![u32::MAX; max_index] } } - pub fn record(&mut self, def_id: DefId, position: usize) { + pub fn record(&mut self, def_id: DefId, entry: Lazy) { assert!(def_id.is_local()); - self.record_index(def_id.index, position); + self.record_index(def_id.index, entry); } - pub fn record_index(&mut self, item: DefIndex, position: usize) { + pub fn record_index(&mut self, item: DefIndex, entry: Lazy) { let item = item.as_usize(); - assert!(position < (u32::MAX as usize)); - let position = position as u32; + assert!(entry.position < (u32::MAX as usize)); + let position = entry.position as u32; assert!(self.positions[item] == u32::MAX, "recorded position for item {:?} twice, first at {:?} and now at {:?}", @@ -103,16 +51,52 @@ impl IndexData { self.positions[item] = position.to_le(); } - pub fn write_index(&self, buf: &mut Cursor>) { + pub fn write_index(&self, buf: &mut Cursor>) -> LazySeq { + let pos = buf.position(); buf.write_all(words_to_bytes(&self.positions)).unwrap(); + LazySeq::with_position_and_length(pos as usize, self.positions.len()) + } +} + +impl<'tcx> LazySeq { + /// Given the metadata, extract out the offset of a particular + /// DefIndex (if any). + #[inline(never)] + pub fn lookup(&self, bytes: &[u8], def_index: DefIndex) -> Option>> { + let words = &bytes_to_words(&bytes[self.position..])[..self.len]; + let index = def_index.as_usize(); + + debug!("Index::lookup: index={:?} words.len={:?}", + index, words.len()); + + let position = u32::from_le(words[index]); + if position == u32::MAX { + debug!("Index::lookup: position=u32::MAX"); + None + } else { + debug!("Index::lookup: position={:?}", position); + Some(Lazy::with_position(position as usize)) + } + } + + pub fn iter_enumerated<'a>(&self, bytes: &'a [u8]) + -> impl Iterator>)> + 'a { + let words = &bytes_to_words(&bytes[self.position..])[..self.len]; + words.iter().enumerate().filter_map(|(index, &position)| { + if position == u32::MAX { + None + } else { + let position = u32::from_le(position) as usize; + Some((DefIndex::new(index), Lazy::with_position(position))) + } + }) } } fn bytes_to_words(b: &[u8]) -> &[u32] { - assert!(b.len() % 4 == 0); - unsafe { slice::from_raw_parts(b.as_ptr() as *const u32, b.len()/4) } + unsafe { slice::from_raw_parts(b.as_ptr() as *const u32, b.len() / 4) } } fn words_to_bytes(w: &[u32]) -> &[u8] { - unsafe { slice::from_raw_parts(w.as_ptr() as *const u8, w.len()*4) } + unsafe { slice::from_raw_parts(w.as_ptr() as *const u8, w.len() * 4) } } diff --git a/src/librustc_metadata/index_builder.rs b/src/librustc_metadata/index_builder.rs index 372577e21f116..aeb6f63252c6e 100644 --- a/src/librustc_metadata/index_builder.rs +++ b/src/librustc_metadata/index_builder.rs @@ -56,7 +56,9 @@ //! easily control precisely what data is given to that fn. use encoder::EncodeContext; -use index::IndexData; +use index::Index; +use schema::*; + use rustc::dep_graph::DepNode; use rustc::hir; use rustc::hir::def_id::DefId; @@ -68,7 +70,7 @@ use std::ops::{Deref, DerefMut}; /// Builder that can encode new items, adding them into the index. /// Item encoding cannot be nested. pub struct IndexBuilder<'a, 'b: 'a, 'tcx: 'b> { - items: IndexData, + items: Index, pub ecx: &'a mut EncodeContext<'b, 'tcx>, } @@ -88,16 +90,16 @@ impl<'a, 'b, 'tcx> DerefMut for IndexBuilder<'a, 'b, 'tcx> { impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { pub fn new(ecx: &'a mut EncodeContext<'b, 'tcx>) -> Self { IndexBuilder { - items: IndexData::new(ecx.tcx.map.num_local_def_ids()), + items: Index::new(ecx.tcx.map.num_local_def_ids()), ecx: ecx, } } /// Emit the data for a def-id to the metadata. The function to /// emit the data is `op`, and it will be given `data` as - /// arguments. This `record` function will start/end an RBML tag - /// and record the current offset for use in the index, calling - /// `op` to generate the data in the RBML tag. + /// arguments. This `record` function will call `op` to generate + /// the `Entry` (which may point to other encoded information) + /// and will then record the `Lazy` for use in the index. /// /// In addition, it will setup a dep-graph task to track what data /// `op` accesses to generate the metadata, which is later used by @@ -112,21 +114,17 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { /// content system. pub fn record(&mut self, id: DefId, - op: fn(&mut EncodeContext<'b, 'tcx>, DATA), + op: fn(&mut EncodeContext<'b, 'tcx>, DATA) -> Entry<'tcx>, data: DATA) where DATA: DepGraphRead { - let position = self.ecx.mark_stable_position(); - self.items.record(id, position); let _task = self.tcx.dep_graph.in_task(DepNode::MetaData(id)); - // FIXME(eddyb) Avoid wrapping the entries in docs. - self.ecx.start_tag(0).unwrap(); data.read(self.tcx); - op(&mut self.ecx, data); - self.ecx.end_tag().unwrap(); + let entry = op(&mut self.ecx, data); + self.items.record(id, self.ecx.lazy(&entry)); } - pub fn into_items(self) -> IndexData { + pub fn into_items(self) -> Index { self.items } } diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs index b46c5be9f8a87..4fc5a46762d12 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -29,11 +29,9 @@ #![feature(rustc_private)] #![feature(specialization)] #![feature(staged_api)] -#![cfg_attr(test, feature(test))] #[macro_use] extern crate log; #[macro_use] extern crate syntax; -#[macro_use] #[no_link] extern crate rustc_bitflags; extern crate syntax_pos; extern crate flate; extern crate serialize as rustc_serialize; // used by deriving @@ -48,24 +46,15 @@ extern crate rustc_llvm; extern crate rustc_macro; extern crate rustc_const_math; -#[cfg(test)] -extern crate test; - -mod rbml { - pub mod writer; - pub mod reader; - pub use self::reader::Doc; -} - mod diagnostics; mod astencode; -mod common; mod index_builder; mod index; mod encoder; mod decoder; mod csearch; +mod schema; pub mod creader; pub mod cstore; diff --git a/src/librustc_metadata/loader.rs b/src/librustc_metadata/loader.rs index 883004b8486f1..fc94cec916aad 100644 --- a/src/librustc_metadata/loader.rs +++ b/src/librustc_metadata/loader.rs @@ -212,8 +212,8 @@ //! no means all of the necessary details. Take a look at the rest of //! metadata::loader or metadata::creader for all the juicy details! -use cstore::{MetadataBlob, MetadataVec, MetadataArchive}; -use common::{metadata_encoding_version, rustc_version}; +use cstore::MetadataBlob; +use schema::{METADATA_HEADER, RUSTC_VERSION}; use rustc::hir::svh::Svh; use rustc::session::Session; @@ -382,7 +382,7 @@ impl<'a> Context<'a> { } if !self.rejected_via_version.is_empty() { err.help(&format!("please recompile that crate using this compiler ({})", - rustc_version())); + RUSTC_VERSION)); let mismatches = self.rejected_via_version.iter(); for (i, &CrateMismatch { ref path, ref got }) in mismatches.enumerate() { err.note(&format!("crate `{}` path #{}: {} compiled by {:?}", @@ -510,8 +510,7 @@ impl<'a> Context<'a> { if let Some((ref p, _)) = lib.rlib { err.note(&format!("path: {}", p.display())); } - let crate_info = lib.metadata.get_crate_info(); - note_crate_name(&mut err, &crate_info.name); + note_crate_name(&mut err, &lib.metadata.get_root().name); } err.emit(); None @@ -597,38 +596,37 @@ impl<'a> Context<'a> { } fn crate_matches(&mut self, metadata: &MetadataBlob, libpath: &Path) -> Option { - let crate_rustc_version = metadata.crate_rustc_version(); - if crate_rustc_version != Some(rustc_version()) { - let message = crate_rustc_version.unwrap_or(format!("an unknown compiler")); - info!("Rejecting via version: expected {} got {}", rustc_version(), message); + let root = metadata.get_root(); + if root.rustc_version != RUSTC_VERSION { + info!("Rejecting via version: expected {} got {}", + RUSTC_VERSION, root.rustc_version); self.rejected_via_version.push(CrateMismatch { path: libpath.to_path_buf(), - got: message + got: root.rustc_version }); return None; } - let crate_info = metadata.get_crate_info(); if self.should_match_name { - if self.crate_name != crate_info.name { + if self.crate_name != root.name { info!("Rejecting via crate name"); return None; } } - if crate_info.triple != self.triple { + if root.triple != self.triple { info!("Rejecting via crate triple: expected {} got {}", - self.triple, crate_info.triple); + self.triple, root.triple); self.rejected_via_triple.push(CrateMismatch { path: libpath.to_path_buf(), - got: crate_info.triple + got: root.triple }); return None; } if let Some(myhash) = self.hash { - if *myhash != crate_info.hash { + if *myhash != root.hash { info!("Rejecting via hash: expected {} got {}", - *myhash, crate_info.hash); + *myhash, root.hash); self.rejected_via_hash.push(CrateMismatch { path: libpath.to_path_buf(), got: myhash.to_string() @@ -637,7 +635,7 @@ impl<'a> Context<'a> { } } - Some(crate_info.hash) + Some(root.hash) } @@ -758,11 +756,7 @@ impl ArchiveMetadata { fn verify_decompressed_encoding_version(blob: &MetadataBlob, filename: &Path) -> Result<(), String> { - let data = blob.as_slice_raw(); - if data.len() < 4+metadata_encoding_version.len() || - !<[u8]>::eq(&data[..4], &[0, 0, 0, 0]) || - &data[4..4+metadata_encoding_version.len()] != metadata_encoding_version - { + if !blob.is_compatible() { Err((format!("incompatible metadata version found: '{}'", filename.display()))) } else { @@ -797,7 +791,7 @@ fn get_metadata_section_imp(target: &Target, flavor: CrateFlavor, filename: &Pat filename.display())); } }; - return match ArchiveMetadata::new(archive).map(|ar| MetadataArchive(ar)) { + return match ArchiveMetadata::new(archive).map(|ar| MetadataBlob::Archive(ar)) { None => Err(format!("failed to read rlib metadata: '{}'", filename.display())), Some(blob) => { @@ -832,12 +826,12 @@ fn get_metadata_section_imp(target: &Target, flavor: CrateFlavor, filename: &Pat let cbuf = llvm::LLVMGetSectionContents(si.llsi); let csz = llvm::LLVMGetSectionSize(si.llsi) as usize; let cvbuf: *const u8 = cbuf as *const u8; - let vlen = metadata_encoding_version.len(); + let vlen = METADATA_HEADER.len(); debug!("checking {} bytes of metadata-version stamp", vlen); let minsz = cmp::min(vlen, csz); let buf0 = slice::from_raw_parts(cvbuf, minsz); - let version_ok = buf0 == metadata_encoding_version; + let version_ok = buf0 == METADATA_HEADER; if !version_ok { return Err((format!("incompatible metadata version found: '{}'", filename.display()))); @@ -849,7 +843,7 @@ fn get_metadata_section_imp(target: &Target, flavor: CrateFlavor, filename: &Pat let bytes = slice::from_raw_parts(cvbuf1, csz - vlen); match flate::inflate_bytes(bytes) { Ok(inflated) => { - let blob = MetadataVec(inflated); + let blob = MetadataBlob::Inflated(inflated); verify_decompressed_encoding_version(&blob, filename)?; return Ok(blob); } diff --git a/src/librustc_metadata/rbml/reader.rs b/src/librustc_metadata/rbml/reader.rs deleted file mode 100644 index c4cfc32d63306..0000000000000 --- a/src/librustc_metadata/rbml/reader.rs +++ /dev/null @@ -1,411 +0,0 @@ -// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Really Bad Markup Language (rbml) is an internal serialization format of rustc. -//! This is not intended to be used by users. -//! -//! Originally based on the Extensible Binary Markup Language -//! (ebml; http://www.matroska.org/technical/specs/rfc/index.html), -//! it is now a separate format tuned for the rust object metadata. -//! -//! # Encoding -//! -//! RBML document consists of the tag, length and data. -//! The encoded data can contain multiple RBML documents concatenated. -//! -//! **Tags** are a hint for the following data. -//! Tags are a number from 0x000 to 0xfff, where 0xf0 through 0xff is reserved. -//! Tags less than 0xf0 are encoded in one literal byte. -//! Tags greater than 0xff are encoded in two big-endian bytes, -//! where the tag number is ORed with 0xf000. (E.g. tag 0x123 = `f1 23`) -//! -//! **Lengths** encode the length of the following data. -//! It is a variable-length unsigned isize, and one of the following forms: -//! -//! - `80` through `fe` for lengths up to 0x7e; -//! - `40 ff` through `7f ff` for lengths up to 0x3fff; -//! - `20 40 00` through `3f ff ff` for lengths up to 0x1fffff; -//! - `10 20 00 00` through `1f ff ff ff` for lengths up to 0xfffffff. -//! -//! The "overlong" form is allowed so that the length can be encoded -//! without the prior knowledge of the encoded data. -//! For example, the length 0 can be represented either by `80`, `40 00`, -//! `20 00 00` or `10 00 00 00`. -//! The encoder tries to minimize the length if possible. -//! Also, some predefined tags listed below are so commonly used that -//! their lengths are omitted ("implicit length"). -//! -//! **Data** can be either binary bytes or zero or more nested RBML documents. -//! Nested documents cannot overflow, and should be entirely contained -//! within a parent document. - -#[cfg(test)] -use test::Bencher; - -use std::fmt; -use std::str; - -macro_rules! try_or { - ($e:expr, $r:expr) => ( - match $e { - Ok(x) => x, - Err(_) => return $r - } - ) -} - -#[derive(Clone, Copy)] -pub struct Doc<'a> { - pub data: &'a [u8], - pub start: usize, - pub end: usize, -} - -impl<'doc> Doc<'doc> { - pub fn new(data: &'doc [u8]) -> Doc<'doc> { - Doc { - data: data, - start: 0, - end: data.len(), - } - } - - pub fn at(data: &'doc [u8], start: usize) -> Doc<'doc> { - let elt_tag = tag_at(data, start).unwrap(); - let elt_size = tag_len_at(data, elt_tag.next).unwrap(); - let end = elt_size.next + elt_size.val; - Doc { - data: data, - start: elt_size.next, - end: end, - } - } - - pub fn maybe_child(&self, tag: usize) -> Option> { - let mut pos = self.start; - while pos < self.end { - let elt_tag = try_or!(tag_at(self.data, pos), None); - let elt_size = try_or!(tag_len_at(self.data, elt_tag.next), None); - pos = elt_size.next + elt_size.val; - if elt_tag.val == tag { - return Some(Doc { - data: self.data, - start: elt_size.next, - end: pos, - }); - } - } - None - } - - pub fn child(&self, tag: usize) -> Doc<'doc> { - match self.maybe_child(tag) { - Some(d) => d, - None => { - bug!("failed to find child with tag {:?}", tag); - } - } - } - - pub fn children_of(&self, tag: usize) -> DocsIterator<'doc> { - DocsIterator { d: self.child(tag) } - } -} - -#[derive(Debug)] -pub enum Error { - IntTooBig(usize), - InvalidTag(usize) -} - -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - // FIXME: this should be a more useful display form - fmt::Debug::fmt(self, f) - } -} - -#[derive(Copy, Clone)] -struct Res { - val: usize, - next: usize, -} - -fn tag_at(data: &[u8], start: usize) -> Result { - let v = data[start] as usize; - if v < 0xf0 { - Ok(Res { - val: v, - next: start + 1, - }) - } else if v > 0xf0 { - Ok(Res { - val: ((v & 0xf) << 8) | data[start + 1] as usize, - next: start + 2, - }) - } else { - // every tag starting with byte 0xf0 is an overlong form, which is prohibited. - Err(Error::InvalidTag(v)) - } -} - -#[inline(never)] -fn vuint_at_slow(data: &[u8], start: usize) -> Result { - let a = data[start]; - if a & 0x80 != 0 { - return Ok(Res { - val: (a & 0x7f) as usize, - next: start + 1, - }); - } - if a & 0x40 != 0 { - return Ok(Res { - val: ((a & 0x3f) as usize) << 8 | (data[start + 1] as usize), - next: start + 2, - }); - } - if a & 0x20 != 0 { - return Ok(Res { - val: ((a & 0x1f) as usize) << 16 | (data[start + 1] as usize) << 8 | - (data[start + 2] as usize), - next: start + 3, - }); - } - if a & 0x10 != 0 { - return Ok(Res { - val: ((a & 0x0f) as usize) << 24 | (data[start + 1] as usize) << 16 | - (data[start + 2] as usize) << 8 | - (data[start + 3] as usize), - next: start + 4, - }); - } - Err(Error::IntTooBig(a as usize)) -} - -fn vuint_at(data: &[u8], start: usize) -> Result { - if data.len() - start < 4 { - return vuint_at_slow(data, start); - } - - // Lookup table for parsing EBML Element IDs as per - // http://ebml.sourceforge.net/specs/ The Element IDs are parsed by - // reading a big endian u32 positioned at data[start]. Using the four - // most significant bits of the u32 we lookup in the table below how - // the element ID should be derived from it. - // - // The table stores tuples (shift, mask) where shift is the number the - // u32 should be right shifted with and mask is the value the right - // shifted value should be masked with. If for example the most - // significant bit is set this means it's a class A ID and the u32 - // should be right shifted with 24 and masked with 0x7f. Therefore we - // store (24, 0x7f) at index 0x8 - 0xF (four bit numbers where the most - // significant bit is set). - // - // By storing the number of shifts and masks in a table instead of - // checking in order if the most significant bit is set, the second - // most significant bit is set etc. we can replace up to three - // "and+branch" with a single table lookup which gives us a measured - // speedup of around 2x on x86_64. - static SHIFT_MASK_TABLE: [(usize, u32); 16] = [(0, 0x0), - (0, 0x0fffffff), - (8, 0x1fffff), - (8, 0x1fffff), - (16, 0x3fff), - (16, 0x3fff), - (16, 0x3fff), - (16, 0x3fff), - (24, 0x7f), - (24, 0x7f), - (24, 0x7f), - (24, 0x7f), - (24, 0x7f), - (24, 0x7f), - (24, 0x7f), - (24, 0x7f)]; - - unsafe { - let ptr = data.as_ptr().offset(start as isize) as *const u32; - let val = u32::from_be(*ptr); - - let i = (val >> 28) as usize; - let (shift, mask) = SHIFT_MASK_TABLE[i]; - Ok(Res { - val: ((val >> shift) & mask) as usize, - next: start + ((32 - shift) >> 3), - }) - } -} - -fn tag_len_at(data: &[u8], next: usize) -> Result { - vuint_at(data, next) -} - -pub struct DocsIterator<'a> { - d: Doc<'a>, -} - -impl<'a> Iterator for DocsIterator<'a> { - type Item = Doc<'a>; - - fn next(&mut self) -> Option> { - if self.d.start >= self.d.end { - return None; - } - - let elt_tag = try_or!(tag_at(self.d.data, self.d.start), { - self.d.start = self.d.end; - None - }); - let elt_size = try_or!(tag_len_at(self.d.data, elt_tag.next), { - self.d.start = self.d.end; - None - }); - - let end = elt_size.next + elt_size.val; - let doc = Doc { - data: self.d.data, - start: elt_size.next, - end: end, - }; - - self.d.start = end; - return Some(doc); - } -} - -#[test] -fn test_vuint_at() { - let data = &[ - 0x80, - 0xff, - 0x40, 0x00, - 0x7f, 0xff, - 0x20, 0x00, 0x00, - 0x3f, 0xff, 0xff, - 0x10, 0x00, 0x00, 0x00, - 0x1f, 0xff, 0xff, 0xff - ]; - - let mut res: Res; - - // Class A - res = vuint_at(data, 0).unwrap(); - assert_eq!(res.val, 0); - assert_eq!(res.next, 1); - res = vuint_at(data, res.next).unwrap(); - assert_eq!(res.val, (1 << 7) - 1); - assert_eq!(res.next, 2); - - // Class B - res = vuint_at(data, res.next).unwrap(); - assert_eq!(res.val, 0); - assert_eq!(res.next, 4); - res = vuint_at(data, res.next).unwrap(); - assert_eq!(res.val, (1 << 14) - 1); - assert_eq!(res.next, 6); - - // Class C - res = vuint_at(data, res.next).unwrap(); - assert_eq!(res.val, 0); - assert_eq!(res.next, 9); - res = vuint_at(data, res.next).unwrap(); - assert_eq!(res.val, (1 << 21) - 1); - assert_eq!(res.next, 12); - - // Class D - res = vuint_at(data, res.next).unwrap(); - assert_eq!(res.val, 0); - assert_eq!(res.next, 16); - res = vuint_at(data, res.next).unwrap(); - assert_eq!(res.val, (1 << 28) - 1); - assert_eq!(res.next, 20); -} - -#[bench] -pub fn vuint_at_A_aligned(b: &mut Bencher) { - let data = (0..4 * 100) - .map(|i| { - match i % 2 { - 0 => 0x80, - _ => i as u8, - } - }) - .collect::>(); - let mut sum = 0; - b.iter(|| { - let mut i = 0; - while i < data.len() { - sum += vuint_at(&data, i).unwrap().val; - i += 4; - } - }); -} - -#[bench] -pub fn vuint_at_A_unaligned(b: &mut Bencher) { - let data = (0..4 * 100 + 1) - .map(|i| { - match i % 2 { - 1 => 0x80, - _ => i as u8, - } - }) - .collect::>(); - let mut sum = 0; - b.iter(|| { - let mut i = 1; - while i < data.len() { - sum += vuint_at(&data, i).unwrap().val; - i += 4; - } - }); -} - -#[bench] -pub fn vuint_at_D_aligned(b: &mut Bencher) { - let data = (0..4 * 100) - .map(|i| { - match i % 4 { - 0 => 0x10, - 3 => i as u8, - _ => 0, - } - }) - .collect::>(); - let mut sum = 0; - b.iter(|| { - let mut i = 0; - while i < data.len() { - sum += vuint_at(&data, i).unwrap().val; - i += 4; - } - }); -} - -#[bench] -pub fn vuint_at_D_unaligned(b: &mut Bencher) { - let data = (0..4 * 100 + 1) - .map(|i| { - match i % 4 { - 1 => 0x10, - 0 => i as u8, - _ => 0, - } - }) - .collect::>(); - let mut sum = 0; - b.iter(|| { - let mut i = 1; - while i < data.len() { - sum += vuint_at(&data, i).unwrap().val; - i += 4; - } - }); -} diff --git a/src/librustc_metadata/rbml/writer.rs b/src/librustc_metadata/rbml/writer.rs deleted file mode 100644 index 46b63cb134031..0000000000000 --- a/src/librustc_metadata/rbml/writer.rs +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::io::prelude::*; -use std::io::{self, SeekFrom, Cursor}; - -use rustc_serialize::opaque; - -pub type EncodeResult = io::Result<()>; - -// rbml writing -pub struct Encoder<'a> { - pub opaque: opaque::Encoder<'a>, - size_positions: Vec, - relax_limit: usize, // do not move encoded bytes before this position -} - -const NUM_TAGS: usize = 0x1000; - -fn write_tag(w: &mut W, n: usize) -> EncodeResult { - if n < 0xf0 { - w.write_all(&[n as u8]) - } else if 0x100 <= n && n < NUM_TAGS { - w.write_all(&[0xf0 | (n >> 8) as u8, n as u8]) - } else { - Err(io::Error::new(io::ErrorKind::Other, &format!("invalid tag: {}", n)[..])) - } -} - -fn write_sized_vuint(w: &mut W, n: usize, size: usize) -> EncodeResult { - match size { - 1 => w.write_all(&[0x80 | (n as u8)]), - 2 => w.write_all(&[0x40 | ((n >> 8) as u8), n as u8]), - 3 => w.write_all(&[0x20 | ((n >> 16) as u8), (n >> 8) as u8, n as u8]), - 4 => w.write_all(&[0x10 | ((n >> 24) as u8), (n >> 16) as u8, (n >> 8) as u8, n as u8]), - _ => Err(io::Error::new(io::ErrorKind::Other, &format!("isize too big: {}", n)[..])), - } -} - -pub fn write_vuint(w: &mut W, n: usize) -> EncodeResult { - if n < 0x7f { - return write_sized_vuint(w, n, 1); - } - if n < 0x4000 { - return write_sized_vuint(w, n, 2); - } - if n < 0x200000 { - return write_sized_vuint(w, n, 3); - } - if n < 0x10000000 { - return write_sized_vuint(w, n, 4); - } - Err(io::Error::new(io::ErrorKind::Other, &format!("isize too big: {}", n)[..])) -} - -impl<'a> Encoder<'a> { - pub fn new(cursor: &'a mut Cursor>) -> Encoder<'a> { - Encoder { - opaque: opaque::Encoder::new(cursor), - size_positions: vec![], - relax_limit: 0, - } - } - - pub fn start_tag(&mut self, tag_id: usize) -> EncodeResult { - debug!("Start tag {:?}", tag_id); - - // Write the enum ID: - write_tag(&mut self.opaque.cursor, tag_id)?; - - // Write a placeholder four-byte size. - let cur_pos = self.position(); - self.size_positions.push(cur_pos); - self.opaque.cursor.write_all(&[0, 0, 0, 0]) - } - - pub fn end_tag(&mut self) -> EncodeResult { - let last_size_pos = self.size_positions.pop().unwrap(); - let cur_pos = self.position(); - self.opaque.cursor.seek(SeekFrom::Start(last_size_pos as u64))?; - let size = cur_pos - last_size_pos - 4; - - // relax the size encoding for small tags (bigger tags are costly to move). - // we should never try to move the stable positions, however. - const RELAX_MAX_SIZE: usize = 0x100; - if size <= RELAX_MAX_SIZE && last_size_pos >= self.relax_limit { - // we can't alter the buffer in place, so have a temporary buffer - let mut buf = [0u8; RELAX_MAX_SIZE]; - { - let data = &self.opaque.cursor.get_ref()[last_size_pos + 4..cur_pos]; - buf[..size].copy_from_slice(data); - } - - // overwrite the size and data and continue - write_vuint(&mut self.opaque.cursor, size)?; - self.opaque.cursor.write_all(&buf[..size])?; - } else { - // overwrite the size with an overlong encoding and skip past the data - write_sized_vuint(&mut self.opaque.cursor, size, 4)?; - self.opaque.cursor.seek(SeekFrom::Start(cur_pos as u64))?; - } - - debug!("End tag (size = {:?})", size); - Ok(()) - } - - pub fn wr_tagged_str(&mut self, tag_id: usize, v: &str) -> EncodeResult { - write_tag(&mut self.opaque.cursor, tag_id)?; - write_vuint(&mut self.opaque.cursor, v.len())?; - self.opaque.cursor.write_all(v.as_bytes()) - } - - pub fn position(&mut self) -> usize { - self.opaque.position() as usize - } - - /// Returns the current position while marking it stable, i.e. - /// generated bytes so far wouldn't be affected by relaxation. - pub fn mark_stable_position(&mut self) -> usize { - let pos = self.position(); - if self.relax_limit < pos { - self.relax_limit = pos; - } - let meta_start = 8 + ::common::metadata_encoding_version.len(); - pos - meta_start - } -} diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs new file mode 100644 index 0000000000000..b4ea2b19bf08a --- /dev/null +++ b/src/librustc_metadata/schema.rs @@ -0,0 +1,299 @@ +// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use astencode; +use index; + +use rustc::hir; +use rustc::hir::def; +use rustc::hir::def_id::{DefIndex, DefId}; +use rustc::middle::cstore::{LinkagePreference, NativeLibraryKind}; +use rustc::middle::lang_items; +use rustc::mir; +use rustc::ty::{self, Ty}; +use rustc::session::config::PanicStrategy; + +use rustc_serialize as serialize; +use syntax::{ast, attr}; +use syntax_pos::{self, Span}; + +use std::marker::PhantomData; + +pub const RUSTC_VERSION: &'static str = concat!("rustc ", env!("CFG_VERSION")); + +/// Metadata encoding version. +/// NB: increment this if you change the format of metadata such that +/// the rustc version can't be found to compare with `RUSTC_VERSION`. +pub const METADATA_VERSION: u8 = 3; + +/// Metadata header which includes `METADATA_VERSION`. +/// To get older versions of rustc to ignore this metadata, +/// there are 4 zero bytes at the start, which are treated +/// as a length of 0 by old compilers. +/// +/// This header is followed by the position of the `CrateRoot`. +pub const METADATA_HEADER: &'static [u8; 12] = &[ + 0, 0, 0, 0, + b'r', b'u', b's', b't', + 0, 0, 0, METADATA_VERSION +]; + +/// The shorthand encoding uses an enum's variant index `usize` +/// and is offset by this value so it never matches a real variant. +/// This offset is also chosen so that the first byte is never < 0x80. +pub const SHORTHAND_OFFSET: usize = 0x80; + +/// A value of type T referred to by its absolute position +/// in the metadata, and which can be decoded lazily. +#[must_use] +pub struct Lazy { + pub position: usize, + _marker: PhantomData +} + +impl Lazy { + pub fn with_position(position: usize) -> Lazy { + Lazy { + position: position, + _marker: PhantomData + } + } +} + +impl Copy for Lazy {} +impl Clone for Lazy { + fn clone(&self) -> Self { *self } +} + +impl serialize::UseSpecializedEncodable for Lazy {} +impl serialize::UseSpecializedDecodable for Lazy {} + +/// A sequence of type T referred to by its absolute position +/// in the metadata and length, and which can be decoded lazily. +/// +/// Unlike `Lazy>`, the length is encoded next to the +/// position, not at the position, which means that the length +/// doesn't need to be known before encoding all the elements. +#[must_use] +pub struct LazySeq { + pub len: usize, + pub position: usize, + _marker: PhantomData +} + +impl LazySeq { + pub fn empty() -> LazySeq { + LazySeq::with_position_and_length(0, 0) + } + + pub fn with_position_and_length(position: usize, len: usize) -> LazySeq { + LazySeq { + len: len, + position: position, + _marker: PhantomData + } + } +} + +impl Copy for LazySeq {} +impl Clone for LazySeq { + fn clone(&self) -> Self { *self } +} + +impl serialize::UseSpecializedEncodable for LazySeq {} +impl serialize::UseSpecializedDecodable for LazySeq {} + +#[derive(RustcEncodable, RustcDecodable)] +pub struct CrateRoot { + pub rustc_version: String, + pub name: String, + pub triple: String, + pub hash: hir::svh::Svh, + pub disambiguator: String, + pub panic_strategy: PanicStrategy, + pub plugin_registrar_fn: Option, + pub macro_derive_registrar: Option, + + pub index: LazySeq, + pub crate_deps: LazySeq, + pub dylib_dependency_formats: LazySeq>, + pub native_libraries: LazySeq<(NativeLibraryKind, String)>, + pub lang_items: LazySeq<(DefIndex, usize)>, + pub lang_items_missing: LazySeq, + pub impls: LazySeq, + pub reachable_ids: LazySeq, + pub macro_defs: LazySeq, + pub codemap: LazySeq +} + +#[derive(RustcEncodable, RustcDecodable)] +pub struct CrateDep { + pub name: ast::Name, + pub hash: hir::svh::Svh, + pub explicitly_linked: bool +} + +#[derive(RustcEncodable, RustcDecodable)] +pub struct TraitImpls { + pub trait_id: (u32, DefIndex), + pub impls: LazySeq +} + +#[derive(RustcEncodable, RustcDecodable)] +pub struct MacroDef { + pub name: ast::Name, + pub attrs: Vec, + pub span: Span, + pub body: String +} + +#[derive(RustcEncodable, RustcDecodable)] +pub struct Entry<'tcx> { + pub kind: EntryKind<'tcx>, + pub visibility: ty::Visibility, + pub def_key: Lazy, + pub attributes: LazySeq, + pub children: LazySeq, + pub stability: Option>, + pub deprecation: Option>, + + pub ty: Option>>, + pub inherent_impls: LazySeq, + pub variances: LazySeq, + pub generics: Option>>, + pub predicates: Option>>, + + pub ast: Option>>, + pub mir: Option>> +} + +#[derive(Copy, Clone, RustcEncodable, RustcDecodable)] +pub enum EntryKind<'tcx> { + Const, + ImmStatic, + MutStatic, + ForeignImmStatic, + ForeignMutStatic, + ForeignMod, + Type, + Enum, + Field, + Variant(Lazy), + Struct(Lazy), + Union(Lazy), + Fn(Lazy), + ForeignFn(Lazy), + Mod(Lazy), + Closure(Lazy>), + Trait(Lazy>), + Impl(Lazy>), + DefaultImpl(Lazy>), + Method(Lazy>), + AssociatedType(AssociatedContainer), + AssociatedConst(AssociatedContainer) +} + +#[derive(RustcEncodable, RustcDecodable)] +pub struct ModData { + pub reexports: LazySeq +} + +#[derive(RustcEncodable, RustcDecodable)] +pub struct FnData { + pub constness: hir::Constness, + pub arg_names: LazySeq +} + +#[derive(RustcEncodable, RustcDecodable)] +pub struct VariantData { + pub kind: ty::VariantKind, + pub disr: u64, + + /// If this is a struct's only variant, this + /// is the index of the "struct ctor" item. + pub struct_ctor: Option +} + +#[derive(RustcEncodable, RustcDecodable)] +pub struct TraitData<'tcx> { + pub unsafety: hir::Unsafety, + pub paren_sugar: bool, + pub has_default_impl: bool, + pub trait_ref: Lazy>, + pub super_predicates: Lazy> +} + +#[derive(RustcEncodable, RustcDecodable)] +pub struct ImplData<'tcx> { + pub polarity: hir::ImplPolarity, + pub parent_impl: Option, + pub coerce_unsized_kind: Option, + pub trait_ref: Option>> +} + +/// Describes whether the container of an associated item +/// is a trait or an impl and whether, in a trait, it has +/// a default, or an in impl, whether it's marked "default". +#[derive(Copy, Clone, RustcEncodable, RustcDecodable)] +pub enum AssociatedContainer { + TraitRequired, + TraitWithDefault, + ImplDefault, + ImplFinal +} + +impl AssociatedContainer { + pub fn with_def_id(&self, def_id: DefId) -> ty::ImplOrTraitItemContainer { + match *self { + AssociatedContainer::TraitRequired | + AssociatedContainer::TraitWithDefault => { + ty::TraitContainer(def_id) + } + + AssociatedContainer::ImplDefault | + AssociatedContainer::ImplFinal => { + ty::ImplContainer(def_id) + } + } + } + + pub fn has_body(&self) -> bool { + match *self { + AssociatedContainer::TraitRequired => false, + + AssociatedContainer::TraitWithDefault | + AssociatedContainer::ImplDefault | + AssociatedContainer::ImplFinal => true + } + } + + pub fn defaultness(&self) -> hir::Defaultness { + match *self { + AssociatedContainer::TraitRequired | + AssociatedContainer::TraitWithDefault | + AssociatedContainer::ImplDefault => hir::Defaultness::Default, + + AssociatedContainer::ImplFinal => hir::Defaultness::Final + } + } +} + +#[derive(RustcEncodable, RustcDecodable)] +pub struct MethodData<'tcx> { + pub fn_data: FnData, + pub container: AssociatedContainer, + pub explicit_self: Lazy> +} + +#[derive(RustcEncodable, RustcDecodable)] +pub struct ClosureData<'tcx> { + pub kind: ty::ClosureKind, + pub ty: Lazy> +} diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index d67dcbb4baf0d..e5d4d4a9dae2c 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -674,6 +674,13 @@ fn convert_associated_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, defaultness: hir::Defaultness, ty: Option>) { + let predicates = ty::GenericPredicates { + parent: Some(container.id()), + predicates: vec![] + }; + ccx.tcx.predicates.borrow_mut().insert(ccx.tcx.map.local_def_id(id), + predicates); + let associated_type = Rc::new(ty::AssociatedType { name: name, vis: ty::Visibility::from_hir(vis, id, ccx.tcx), @@ -831,6 +838,9 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { // Convert all the associated types. for impl_item in impl_items { if let hir::ImplItemKind::Type(ref ty) = impl_item.node { + let type_def_id = ccx.tcx.map.local_def_id(impl_item.id); + generics_of_def_id(ccx, type_def_id); + if opt_trait_ref.is_none() { span_err!(tcx.sess, impl_item.span, E0202, "associated types are not allowed in inherent impls"); @@ -898,6 +908,9 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { // Convert all the associated types. for trait_item in trait_items { if let hir::TypeTraitItem(_, ref opt_ty) = trait_item.node { + let type_def_id = ccx.tcx.map.local_def_id(trait_item.id); + generics_of_def_id(ccx, type_def_id); + let typ = opt_ty.as_ref().map({ |ty| ccx.icx(&trait_predicates).to_ty(&ExplicitRscope, &ty) }); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 9f208b7bed70c..0ae059509bd10 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1168,7 +1168,7 @@ impl<'a, 'tcx> Clean for (DefId, &'a ty::PolyFnSig<'tcx>) { Argument { type_: t.clean(cx), id: ast::CRATE_NODE_ID, - name: names.next().unwrap_or("".to_string()), + name: names.next().map_or("".to_string(), |name| name.to_string()), } }).collect(), }, diff --git a/src/rustc/Cargo.lock b/src/rustc/Cargo.lock index d8a02badceede..69e3eab22e912 100644 --- a/src/rustc/Cargo.lock +++ b/src/rustc/Cargo.lock @@ -219,7 +219,6 @@ dependencies = [ "log 0.0.0", "rustc 0.0.0", "rustc_back 0.0.0", - "rustc_bitflags 0.0.0", "rustc_const_math 0.0.0", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", diff --git a/src/test/run-pass-fulldeps/issue-11881.rs b/src/test/run-pass-fulldeps/issue-11881.rs index 8369d08db36d4..914e3dd493248 100644 --- a/src/test/run-pass-fulldeps/issue-11881.rs +++ b/src/test/run-pass-fulldeps/issue-11881.rs @@ -34,14 +34,14 @@ struct Bar { enum WireProtocol { JSON, - RBML, + Opaque, // ... } fn encode_json(val: &T, wr: &mut Cursor>) { write!(wr, "{}", json::as_json(val)); } -fn encode_rbml(val: &T, wr: &mut Cursor>) { +fn encode_opaque(val: &T, wr: &mut Cursor>) { let mut encoder = opaque::Encoder::new(wr); val.encode(&mut encoder); } @@ -52,6 +52,6 @@ pub fn main() { let proto = WireProtocol::JSON; match proto { WireProtocol::JSON => encode_json(&target, &mut wr), - WireProtocol::RBML => encode_rbml(&target, &mut wr) + WireProtocol::Opaque => encode_opaque(&target, &mut wr) } } From dc26a23301d8c435fae647174bd2906babbdb2f9 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Sat, 17 Sep 2016 10:33:47 +0300 Subject: [PATCH 29/39] rustc_metadata: reduce Lazy{,Seq} overhead by using a relative encoding. --- src/librustc_metadata/decoder.rs | 47 +++++++++++++++++--- src/librustc_metadata/encoder.rs | 73 +++++++++++++++++++++++++------- src/librustc_metadata/schema.rs | 54 +++++++++++++++++++++-- 3 files changed, 148 insertions(+), 26 deletions(-) diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 7a4d3ed657a1e..973ef6030a3e9 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -52,8 +52,11 @@ pub struct DecodeContext<'a, 'tcx: 'a> { cdata: Option<&'a CrateMetadata>, from_id_range: IdRange, to_id_range: IdRange, + // Cache the last used filemap for translating spans as an optimization. last_filemap_index: usize, + + lazy_state: LazyState } /// Abstract over the various ways one can create metadata decoders. @@ -73,7 +76,8 @@ pub trait Metadata<'a, 'tcx>: Copy { tcx: self.tcx(), from_id_range: id_range, to_id_range: id_range, - last_filemap_index: 0 + last_filemap_index: 0, + lazy_state: LazyState::NoNode } } } @@ -114,13 +118,16 @@ impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadata, TyCtxt<'a, 'tcx, 'tcx> impl<'a, 'tcx: 'a, T: Decodable> Lazy { pub fn decode>(self, meta: M) -> T { - T::decode(&mut meta.decoder(self.position)).unwrap() + let mut dcx = meta.decoder(self.position); + dcx.lazy_state = LazyState::NodeStart(self.position); + T::decode(&mut dcx).unwrap() } } impl<'a, 'tcx: 'a, T: Decodable> LazySeq { pub fn decode>(self, meta: M) -> impl Iterator + 'a { let mut dcx = meta.decoder(self.position); + dcx.lazy_state = LazyState::NodeStart(self.position); (0..self.len).map(move |_| { T::decode(&mut dcx).unwrap() }) @@ -137,12 +144,33 @@ impl<'a, 'tcx> DecodeContext<'a, 'tcx> { } fn with_position R, R>(&mut self, pos: usize, f: F) -> R { - let new = opaque::Decoder::new(self.opaque.data, pos); - let old = mem::replace(&mut self.opaque, new); + let new_opaque = opaque::Decoder::new(self.opaque.data, pos); + let old_opaque = mem::replace(&mut self.opaque, new_opaque); + let old_state = mem::replace(&mut self.lazy_state, LazyState::NoNode); let r = f(self); - self.opaque = old; + self.opaque = old_opaque; + self.lazy_state = old_state; r } + + fn read_lazy_distance(&mut self, min_size: usize) + -> Result::Error> { + let distance = self.read_usize()?; + let position = match self.lazy_state { + LazyState::NoNode => { + bug!("read_lazy_distance: outside of a metadata node") + } + LazyState::NodeStart(start) => { + assert!(distance + min_size <= start); + start - distance - min_size + } + LazyState::Previous(last_min_end) => { + last_min_end + distance + } + }; + self.lazy_state = LazyState::Previous(position + min_size); + Ok(position) + } } macro_rules! decoder_methods { @@ -185,14 +213,19 @@ impl<'doc, 'tcx> Decoder for DecodeContext<'doc, 'tcx> { impl<'a, 'tcx, T> SpecializedDecoder> for DecodeContext<'a, 'tcx> { fn specialized_decode(&mut self) -> Result, Self::Error> { - Ok(Lazy::with_position(self.read_usize()?)) + Ok(Lazy::with_position(self.read_lazy_distance(Lazy::::min_size())?)) } } impl<'a, 'tcx, T> SpecializedDecoder> for DecodeContext<'a, 'tcx> { fn specialized_decode(&mut self) -> Result, Self::Error> { let len = self.read_usize()?; - Ok(LazySeq::with_position_and_length(self.read_usize()?, len)) + let position = if len == 0 { + 0 + } else { + self.read_lazy_distance(LazySeq::::min_size(len))? + }; + Ok(LazySeq::with_position_and_length(position, len)) } } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 185aa9e3b921c..0f067270b80f5 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -53,6 +53,7 @@ pub struct EncodeContext<'a, 'tcx: 'a> { reachable: &'a NodeSet, mir_map: &'a MirMap<'tcx>, + lazy_state: LazyState, type_shorthands: FnvHashMap, usize>, predicate_shorthands: FnvHashMap, usize>, } @@ -95,14 +96,17 @@ impl<'a, 'tcx> Encoder for EncodeContext<'a, 'tcx> { impl<'a, 'tcx, T> SpecializedEncoder> for EncodeContext<'a, 'tcx> { fn specialized_encode(&mut self, lazy: &Lazy) -> Result<(), Self::Error> { - self.emit_usize(lazy.position) + self.emit_lazy_distance(lazy.position, Lazy::::min_size()) } } impl<'a, 'tcx, T> SpecializedEncoder> for EncodeContext<'a, 'tcx> { fn specialized_encode(&mut self, seq: &LazySeq) -> Result<(), Self::Error> { self.emit_usize(seq.len)?; - self.emit_usize(seq.position) + if seq.len == 0 { + return Ok(()); + } + self.emit_lazy_distance(seq.position, LazySeq::::min_size(seq.len)) } } @@ -129,24 +133,62 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.opaque.position() } - pub fn lazy(&mut self, value: &T) -> Lazy { + fn emit_node R, R>(&mut self, f: F) -> R { + assert_eq!(self.lazy_state, LazyState::NoNode); let pos = self.position(); - value.encode(self).unwrap(); - Lazy::with_position(pos) + self.lazy_state = LazyState::NodeStart(pos); + let r = f(self, pos); + self.lazy_state = LazyState::NoNode; + r + } + + fn emit_lazy_distance(&mut self, position: usize, min_size: usize) + -> Result<(), ::Error> { + let min_end = position + min_size; + let distance = match self.lazy_state { + LazyState::NoNode => { + bug!("emit_lazy_distance: outside of a metadata node") + } + LazyState::NodeStart(start) => { + assert!(min_end <= start); + start - min_end + } + LazyState::Previous(last_min_end) => { + assert!(last_min_end <= position); + position - last_min_end + } + }; + self.lazy_state = LazyState::Previous(min_end); + self.emit_usize(distance) + } + + pub fn lazy(&mut self, value: &T) -> Lazy { + self.emit_node(|ecx, pos| { + value.encode(ecx).unwrap(); + + assert!(pos + Lazy::::min_size() <= ecx.position()); + Lazy::with_position(pos) + }) } fn lazy_seq(&mut self, iter: I) -> LazySeq where I: IntoIterator, T: Encodable { - let pos = self.position(); - let len = iter.into_iter().map(|value| value.encode(self).unwrap()).count(); - LazySeq::with_position_and_length(pos, len) + self.emit_node(|ecx, pos| { + let len = iter.into_iter().map(|value| value.encode(ecx).unwrap()).count(); + + assert!(pos + LazySeq::::min_size(len) <= ecx.position()); + LazySeq::with_position_and_length(pos, len) + }) } fn lazy_seq_ref<'b, I, T>(&mut self, iter: I) -> LazySeq where I: IntoIterator, T: 'b + Encodable { - let pos = self.position(); - let len = iter.into_iter().map(|value| value.encode(self).unwrap()).count(); - LazySeq::with_position_and_length(pos, len) + self.emit_node(|ecx, pos| { + let len = iter.into_iter().map(|value| value.encode(ecx).unwrap()).count(); + + assert!(pos + LazySeq::::min_size(len) <= ecx.position()); + LazySeq::with_position_and_length(pos, len) + }) } /// Encode the given value or a previously cached shorthand. @@ -1262,16 +1304,16 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { None }, - index: index, crate_deps: crate_deps, dylib_dependency_formats: dylib_dependency_formats, - native_libraries: native_libraries, lang_items: lang_items, lang_items_missing: lang_items_missing, + native_libraries: native_libraries, + codemap: codemap, + macro_defs: macro_defs, impls: impls, reachable_ids: reachable_ids, - macro_defs: macro_defs, - codemap: codemap + index: index, }); let total_bytes = self.position(); @@ -1345,6 +1387,7 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, cstore: cstore, reachable: reachable, mir_map: mir_map, + lazy_state: LazyState::NoNode, type_shorthands: Default::default(), predicate_shorthands: Default::default() }.encode_crate_root(); diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index b4ea2b19bf08a..956577ed8fb89 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -52,6 +52,19 @@ pub const SHORTHAND_OFFSET: usize = 0x80; /// A value of type T referred to by its absolute position /// in the metadata, and which can be decoded lazily. +/// +/// Metadata is effective a tree, encoded in post-order, +/// and with the root's position written next to the header. +/// That means every single `Lazy` points to some previous +/// location in the metadata and is part of a larger node. +/// +/// The first `Lazy` in a node is encoded as the backwards +/// distance from the position where the containing node +/// starts and where the `Lazy` points to, while the rest +/// use the forward distance from the previous `Lazy`. +/// Distances start at 1, as 0-byte nodes are invalid. +/// Also invalid are nodes being referred in a different +/// order than they were encoded in. #[must_use] pub struct Lazy { pub position: usize, @@ -65,6 +78,12 @@ impl Lazy { _marker: PhantomData } } + + /// Returns the minimum encoded size of a value of type `T`. + // FIXME(eddyb) Give better estimates for certain types. + pub fn min_size() -> usize { + 1 + } } impl Copy for Lazy {} @@ -77,10 +96,16 @@ impl serialize::UseSpecializedDecodable for Lazy {} /// A sequence of type T referred to by its absolute position /// in the metadata and length, and which can be decoded lazily. +/// The sequence is a single node for the purposes of `Lazy`. /// /// Unlike `Lazy>`, the length is encoded next to the /// position, not at the position, which means that the length /// doesn't need to be known before encoding all the elements. +/// +/// If the length is 0, no position is encoded, but otherwise, +/// the encoding is that of `Lazy`, with the distinction that +/// the minimal distance the length of the sequence, i.e. +/// it's assumed there's no 0-byte element in the sequence. #[must_use] pub struct LazySeq { pub len: usize, @@ -100,6 +125,11 @@ impl LazySeq { _marker: PhantomData } } + + /// Returns the minimum encoded size of `length` values of type `T`. + pub fn min_size(length: usize) -> usize { + length + } } impl Copy for LazySeq {} @@ -110,6 +140,22 @@ impl Clone for LazySeq { impl serialize::UseSpecializedEncodable for LazySeq {} impl serialize::UseSpecializedDecodable for LazySeq {} +/// Encoding / decoding state for `Lazy` and `LazySeq`. +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum LazyState { + /// Outside of a metadata node. + NoNode, + + /// Inside a metadata node, and before any `Lazy` or `LazySeq`. + /// The position is that of the node itself. + NodeStart(usize), + + /// Inside a metadata node, with a previous `Lazy` or `LazySeq`. + /// The position is a conservative estimate of where that + /// previous `Lazy` / `LazySeq` would end (see their comments). + Previous(usize) +} + #[derive(RustcEncodable, RustcDecodable)] pub struct CrateRoot { pub rustc_version: String, @@ -121,16 +167,16 @@ pub struct CrateRoot { pub plugin_registrar_fn: Option, pub macro_derive_registrar: Option, - pub index: LazySeq, pub crate_deps: LazySeq, pub dylib_dependency_formats: LazySeq>, - pub native_libraries: LazySeq<(NativeLibraryKind, String)>, pub lang_items: LazySeq<(DefIndex, usize)>, pub lang_items_missing: LazySeq, + pub native_libraries: LazySeq<(NativeLibraryKind, String)>, + pub codemap: LazySeq, + pub macro_defs: LazySeq, pub impls: LazySeq, pub reachable_ids: LazySeq, - pub macro_defs: LazySeq, - pub codemap: LazySeq + pub index: LazySeq, } #[derive(RustcEncodable, RustcDecodable)] From dadbaa48ac5a86810aea17accd2f85194dc8cfd3 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Sat, 17 Sep 2016 13:34:55 +0300 Subject: [PATCH 30/39] rustc_metadata: move opt_item_name to TyCtxt::item_name. --- src/librustc/hir/map/definitions.rs | 26 +++++++++++++- src/librustc/middle/cstore.rs | 4 +-- src/librustc/ty/item_path.rs | 3 +- src/librustc/ty/mod.rs | 21 ++++++++--- src/librustc_metadata/csearch.rs | 10 ------ src/librustc_metadata/decoder.rs | 39 +++------------------ src/librustc_resolve/build_reduced_graph.rs | 3 +- 7 files changed, 51 insertions(+), 55 deletions(-) diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index c0c28939ab27f..af751e51d931e 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -14,7 +14,7 @@ use rustc_data_structures::fnv::FnvHashMap; use std::fmt::Write; use std::hash::{Hash, Hasher, SipHasher}; use syntax::{ast, visit}; -use syntax::parse::token::InternedString; +use syntax::parse::token::{self, InternedString}; use ty::TyCtxt; use util::nodemap::NodeMap; @@ -326,6 +326,30 @@ impl Definitions { } impl DefPathData { + pub fn get_opt_name(&self) -> Option { + use self::DefPathData::*; + match *self { + TypeNs(ref name) | + ValueNs(ref name) | + Module(ref name) | + MacroDef(ref name) | + TypeParam(ref name) | + LifetimeDef(ref name) | + EnumVariant(ref name) | + Binding(ref name) | + Field(ref name) => Some(token::intern(name)), + + Impl | + CrateRoot | + InlinedRoot(_) | + Misc | + ClosureExpr | + StructCtor | + Initializer | + ImplTrait => None + } + } + pub fn as_interned_str(&self) -> InternedString { use self::DefPathData::*; match *self { diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 658825d417e4c..2ebf7ba6d53d2 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -132,7 +132,6 @@ pub trait CrateStore<'tcx> { fn item_type<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> Ty<'tcx>; fn visible_parent_map<'a>(&'a self) -> ::std::cell::RefMut<'a, DefIdMap>; - fn opt_item_name(&self, def: DefId) -> Option; fn item_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> ty::GenericPredicates<'tcx>; fn item_super_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) @@ -293,7 +292,6 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { fn visible_parent_map<'a>(&'a self) -> ::std::cell::RefMut<'a, DefIdMap> { bug!("visible_parent_map") } - fn opt_item_name(&self, def: DefId) -> Option { bug!("opt_item_name") } fn item_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> ty::GenericPredicates<'tcx> { bug!("item_predicates") } fn item_super_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) @@ -424,4 +422,4 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { pub trait MacroLoader { fn load_crate(&mut self, extern_crate: &ast::Item, allows_macros: bool) -> Vec; -} \ No newline at end of file +} diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index 5f121b568c3af..ca12dde73b84b 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -138,7 +138,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } - cur_path.push(self.sess.cstore.opt_item_name(cur_def).unwrap_or_else(|| + cur_path.push(self.sess.cstore.def_key(cur_def) + .disambiguated_data.data.get_opt_name().unwrap_or_else(|| token::intern(""))); match visible_parent_map.get(&cur_def) { Some(&def) => cur_def = def, diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 8a9b2846ac666..d7076ddf0445d 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -21,7 +21,7 @@ use dep_graph::{self, DepNode}; use hir::map as ast_map; use middle; use hir::def::{Def, PathResolution, ExportMap}; -use hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; +use hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem}; use middle::region::{CodeExtent, ROOT_CODE_EXTENT}; use traits; @@ -43,7 +43,7 @@ use std::slice; use std::vec::IntoIter; use syntax::ast::{self, Name, NodeId}; use syntax::attr; -use syntax::parse::token::InternedString; +use syntax::parse::token::{self, InternedString}; use syntax_pos::{DUMMY_SP, Span}; use rustc_const_math::ConstInt; @@ -2390,10 +2390,21 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn item_name(self, id: DefId) -> ast::Name { if let Some(id) = self.map.as_local_node_id(id) { self.map.name(id) + } else if id.index == CRATE_DEF_INDEX { + token::intern(&self.sess.cstore.original_crate_name(id.krate)) } else { - self.sess.cstore.opt_item_name(id).unwrap_or_else(|| { - bug!("item_name: no name for {:?}", self.def_path(id)); - }) + let def_key = self.sess.cstore.def_key(id); + // The name of a StructCtor is that of its struct parent. + if let ast_map::DefPathData::StructCtor = def_key.disambiguated_data.data { + self.item_name(DefId { + krate: id.krate, + index: def_key.parent.unwrap() + }) + } else { + def_key.disambiguated_data.data.get_opt_name().unwrap_or_else(|| { + bug!("item_name: no name for {:?}", self.def_path(id)); + }) + } } } diff --git a/src/librustc_metadata/csearch.rs b/src/librustc_metadata/csearch.rs index f508c5dc9cfb0..7013720224a64 100644 --- a/src/librustc_metadata/csearch.rs +++ b/src/librustc_metadata/csearch.rs @@ -127,16 +127,6 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { self.get_crate_data(did.krate).get_fn_arg_names(did.index) } - fn opt_item_name(&self, def: DefId) -> Option { - self.dep_graph.read(DepNode::MetaData(def)); - let cdata = self.get_crate_data(def.krate); - if def.index == CRATE_DEF_INDEX { - Some(token::intern(&cdata.name())) - } else { - cdata.maybe_get_item_name(def.index) - } - } - fn inherent_implementations_for_type(&self, def_id: DefId) -> Vec { self.dep_graph.read(DepNode::MetaData(def_id)); diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 973ef6030a3e9..d98e8d62c2d15 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -43,7 +43,6 @@ use rustc_serialize::{Decodable, Decoder, SpecializedDecoder, opaque}; use syntax::attr; use syntax::ast::{self, NodeId}; use syntax::codemap; -use syntax::parse::token; use syntax_pos::{self, Span, BytePos, Pos}; pub struct DecodeContext<'a, 'tcx: 'a> { @@ -469,32 +468,6 @@ impl<'tcx> EntryKind<'tcx> { } } -fn def_key_name(def_key: &hir_map::DefKey) -> Option { - match def_key.disambiguated_data.data { - DefPathData::TypeNs(ref name) | - DefPathData::ValueNs(ref name) | - DefPathData::Module(ref name) | - DefPathData::MacroDef(ref name) | - DefPathData::TypeParam(ref name) | - DefPathData::LifetimeDef(ref name) | - DefPathData::EnumVariant(ref name) | - DefPathData::Field(ref name) | - DefPathData::Binding(ref name) => { - Some(token::intern(name)) - } - - DefPathData::InlinedRoot(_) => bug!("unexpected DefPathData"), - - DefPathData::CrateRoot | - DefPathData::Misc | - DefPathData::Impl | - DefPathData::ClosureExpr | - DefPathData::StructCtor | - DefPathData::Initializer | - DefPathData::ImplTrait => None - } -} - impl<'a, 'tcx> CrateMetadata { fn maybe_entry(&self, item_id: DefIndex) -> Option>> { self.root.index.lookup(self.blob.raw_bytes(), item_id) @@ -518,7 +491,8 @@ impl<'a, 'tcx> CrateMetadata { } fn item_name(&self, item: &Entry<'tcx>) -> ast::Name { - def_key_name(&item.def_key.decode(self)).expect("no name in item_name") + item.def_key.decode(self).disambiguated_data.data.get_opt_name() + .expect("no name in item_name") } pub fn get_def(&self, index: DefIndex) -> Option { @@ -708,7 +682,8 @@ impl<'a, 'tcx> CrateMetadata { _ => {} } - if let Some(name) = def_key_name(&child.def_key.decode(self)) { + let def_key = child.def_key.decode(self); + if let Some(name) = def_key.disambiguated_data.data.get_opt_name() { callback(def::Export { def_id: self.local_def_id(child_index), name: name @@ -724,10 +699,6 @@ impl<'a, 'tcx> CrateMetadata { } } - pub fn maybe_get_item_name(&self, id: DefIndex) -> Option { - def_key_name(&self.entry(id).def_key.decode(self)) - } - pub fn maybe_get_item_ast(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefIndex) -> Option<&'tcx InlinedItem> { debug!("Looking up item: {:?}", id); @@ -757,7 +728,7 @@ impl<'a, 'tcx> CrateMetadata { let parent_and_name = || { let def_key = item.def_key.decode(self); (self.local_def_id(def_key.parent.unwrap()), - def_key_name(&def_key).unwrap()) + def_key.disambiguated_data.data.get_opt_name().unwrap()) }; Some(match item.kind { diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 1714398f2fed0..3c5e9e6cd3a99 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -436,7 +436,8 @@ impl<'b> Resolver<'b> { let trait_item_def_ids = self.session.cstore.impl_or_trait_items(def_id); for &trait_item_def in &trait_item_def_ids { let trait_item_name = - self.session.cstore.opt_item_name(trait_item_def) + self.session.cstore.def_key(trait_item_def) + .disambiguated_data.data.get_opt_name() .expect("opt_item_name returned None for trait"); debug!("(building reduced graph for external crate) ... adding trait item \ From f2283a7be0afb00ff4d6bb1e179a75811286d2cd Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Sat, 17 Sep 2016 14:25:19 +0300 Subject: [PATCH 31/39] rustc_metadata: fix for the new `?` ambiguity around collect. --- src/librustc_metadata/decoder.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index d98e8d62c2d15..e718a107bbe29 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -366,7 +366,7 @@ impl<'a, 'tcx> SpecializedDecoder> for DecodeContext } else { ty::Predicate::decode(self) } - }).collect()? + }).collect::, _>>()? }) } } From b01d4891e2935cf24242e44b50dfa37efc28d28c Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Sat, 17 Sep 2016 19:06:21 +0300 Subject: [PATCH 32/39] rustc: don't recurse through nested items in decoded HIR fragments. --- src/librustc/hir/map/collector.rs | 10 +++++++++- src/librustc/hir/map/def_collector.rs | 9 --------- src/test/run-pass/auxiliary/issue-17718-aux.rs | 3 +-- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index 6c6de8e890245..3d9031a136e28 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -27,6 +27,10 @@ pub struct NodeCollector<'ast> { pub map: Vec>, /// The parent of this node pub parent_node: NodeId, + /// If true, completely ignore nested items. We set this when loading + /// HIR from metadata, since in that case we only want the HIR for + /// one specific item (and not the ones nested inside of it). + pub ignore_nested_items: bool } impl<'ast> NodeCollector<'ast> { @@ -35,6 +39,7 @@ impl<'ast> NodeCollector<'ast> { krate: krate, map: vec![], parent_node: CRATE_NODE_ID, + ignore_nested_items: false }; collector.insert_entry(CRATE_NODE_ID, RootCrate); @@ -52,6 +57,7 @@ impl<'ast> NodeCollector<'ast> { krate: krate, map: map, parent_node: parent_node, + ignore_nested_items: true }; assert_eq!(parent_def_path.krate, parent_def_id.krate); @@ -88,7 +94,9 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> { /// their outer items. fn visit_nested_item(&mut self, item: ItemId) { debug!("visit_nested_item: {:?}", item); - self.visit_item(self.krate.item(item.id)) + if !self.ignore_nested_items { + self.visit_item(self.krate.item(item.id)) + } } fn visit_item(&mut self, i: &'ast Item) { diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index 29fb19fd42152..ea1f8aac7a55a 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -285,15 +285,6 @@ impl<'ast> visit::Visitor for DefCollector<'ast> { // We walk the HIR rather than the AST when reading items from metadata. impl<'ast> intravisit::Visitor<'ast> for DefCollector<'ast> { - /// Because we want to track parent items and so forth, enable - /// deep walking so that we walk nested items in the context of - /// their outer items. - fn visit_nested_item(&mut self, item_id: hir::ItemId) { - debug!("visit_nested_item: {:?}", item_id); - let item = self.hir_crate.unwrap().item(item_id.id); - self.visit_item(item) - } - fn visit_item(&mut self, i: &'ast hir::Item) { debug!("visit_item: {:?}", i); diff --git a/src/test/run-pass/auxiliary/issue-17718-aux.rs b/src/test/run-pass/auxiliary/issue-17718-aux.rs index 373fc04217540..cf7fdd7f983f0 100644 --- a/src/test/run-pass/auxiliary/issue-17718-aux.rs +++ b/src/test/run-pass/auxiliary/issue-17718-aux.rs @@ -14,11 +14,10 @@ use std::sync::atomic; pub const C1: usize = 1; pub const C2: atomic::AtomicUsize = atomic::AtomicUsize::new(0); -pub const C3: fn() = foo; +pub const C3: fn() = { fn foo() {} foo }; pub const C4: usize = C1 * C1 + C1 / C1; pub const C5: &'static usize = &C4; pub static S1: usize = 3; pub static S2: atomic::AtomicUsize = atomic::AtomicUsize::new(0); -fn foo() {} From 221d1a97e505d00fc1664c5b2d9041f8b78aa933 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Sat, 17 Sep 2016 23:31:03 +0300 Subject: [PATCH 33/39] serialize: allow specifying the default behavior for specializations. --- src/librustc/hir/def_id.rs | 16 +++++++++++++--- src/librustc/ty/mod.rs | 4 ++-- src/libserialize/serialize.rs | 36 ++++++++++++++++++----------------- src/libsyntax/ast.rs | 14 ++++++++++++-- src/libsyntax_pos/lib.rs | 14 +++++++++++--- 5 files changed, 57 insertions(+), 27 deletions(-) diff --git a/src/librustc/hir/def_id.rs b/src/librustc/hir/def_id.rs index f36fcfd518733..399243551d651 100644 --- a/src/librustc/hir/def_id.rs +++ b/src/librustc/hir/def_id.rs @@ -11,12 +11,12 @@ use ty; use rustc_data_structures::indexed_vec::Idx; -use serialize; +use serialize::{self, Encoder, Decoder}; use std::fmt; use std::u32; -#[derive(Clone, Copy, Eq, Ord, PartialOrd, PartialEq, RustcEncodable, Hash, Debug)] +#[derive(Clone, Copy, Eq, Ord, PartialOrd, PartialEq, Hash, Debug)] pub struct CrateNum(u32); impl Idx for CrateNum { @@ -59,7 +59,17 @@ impl fmt::Display for CrateNum { } } -impl serialize::UseSpecializedDecodable for CrateNum {} +impl serialize::UseSpecializedEncodable for CrateNum { + fn default_encode(&self, s: &mut S) -> Result<(), S::Error> { + s.emit_u32(self.0) + } +} + +impl serialize::UseSpecializedDecodable for CrateNum { + fn default_decode(d: &mut D) -> Result { + d.read_u32().map(CrateNum) + } +} /// A DefIndex is an index into the hir-map for a crate, identifying a /// particular definition. It should really be considered an interned diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index d7076ddf0445d..9eb87fa2ed43c 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1470,8 +1470,8 @@ impl<'tcx, 'container> Hash for AdtDefData<'tcx, 'container> { } } -impl<'tcx> Encodable for AdtDef<'tcx> { - fn encode(&self, s: &mut S) -> Result<(), S::Error> { +impl<'tcx> serialize::UseSpecializedEncodable for AdtDef<'tcx> { + fn default_encode(&self, s: &mut S) -> Result<(), S::Error> { self.did.encode(s) } } diff --git a/src/libserialize/serialize.rs b/src/libserialize/serialize.rs index 88f6c12e98040..6650a981884d8 100644 --- a/src/libserialize/serialize.rs +++ b/src/libserialize/serialize.rs @@ -691,42 +691,39 @@ impl SpecializationError for E { /// Implement this trait on encoders, with `T` being the type /// you want to encode (employing `UseSpecializedEncodable`), /// using a strategy specific to the encoder. -/// Can also be implemented alongside `UseSpecializedEncodable` -/// to provide a default `specialized_encode` for encoders -/// which do not implement `SpecializedEncoder` themselves. -pub trait SpecializedEncoder: Encoder { +pub trait SpecializedEncoder: Encoder { /// Encode the value in a manner specific to this encoder state. - /// Defaults to returning an error (see `SpecializationError`). fn specialized_encode(&mut self, value: &T) -> Result<(), Self::Error>; } -impl SpecializedEncoder for E { - default fn specialized_encode(&mut self, _: &T) -> Result<(), E::Error> { - Err(E::Error::not_found::("SpecializedEncoder", "specialized_encode")) +impl SpecializedEncoder for E { + default fn specialized_encode(&mut self, value: &T) -> Result<(), E::Error> { + value.default_encode(self) } } /// Implement this trait on decoders, with `T` being the type /// you want to decode (employing `UseSpecializedDecodable`), /// using a strategy specific to the decoder. -/// Can also be implemented alongside `UseSpecializedDecodable` -/// to provide a default `specialized_decode` for decoders -/// which do not implement `SpecializedDecoder` themselves. -pub trait SpecializedDecoder: Decoder { +pub trait SpecializedDecoder: Decoder { /// Decode a value in a manner specific to this decoder state. - /// Defaults to returning an error (see `SpecializationError`). fn specialized_decode(&mut self) -> Result; } -impl SpecializedDecoder for D { +impl SpecializedDecoder for D { default fn specialized_decode(&mut self) -> Result { - Err(D::Error::not_found::("SpecializedDecoder", "specialized_decode")) + T::default_decode(self) } } /// Implement this trait on your type to get an `Encodable` /// implementation which goes through `SpecializedEncoder`. -pub trait UseSpecializedEncodable {} +pub trait UseSpecializedEncodable { + /// Defaults to returning an error (see `SpecializationError`). + fn default_encode(&self, _: &mut E) -> Result<(), E::Error> { + Err(E::Error::not_found::("SpecializedEncoder", "specialized_encode")) + } +} impl Encodable for T { default fn encode(&self, e: &mut E) -> Result<(), E::Error> { @@ -736,7 +733,12 @@ impl Encodable for T { /// Implement this trait on your type to get an `Decodable` /// implementation which goes through `SpecializedDecoder`. -pub trait UseSpecializedDecodable: Sized {} +pub trait UseSpecializedDecodable: Sized { + /// Defaults to returning an error (see `SpecializationError`). + fn default_decode(_: &mut D) -> Result { + Err(D::Error::not_found::("SpecializedDecoder", "specialized_decode")) + } +} impl Decodable for T { default fn decode(d: &mut D) -> Result { diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 70e614f9c9a91..c18b36161dfcf 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -300,7 +300,7 @@ pub struct ParenthesizedParameterData { pub output: Option>, } -#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, RustcEncodable, Hash, Debug)] +#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash, Debug)] pub struct NodeId(u32); impl NodeId { @@ -328,7 +328,17 @@ impl fmt::Display for NodeId { } } -impl serialize::UseSpecializedDecodable for NodeId {} +impl serialize::UseSpecializedEncodable for NodeId { + fn default_encode(&self, s: &mut S) -> Result<(), S::Error> { + s.emit_u32(self.0) + } +} + +impl serialize::UseSpecializedDecodable for NodeId { + fn default_decode(d: &mut D) -> Result { + d.read_u32().map(NodeId) + } +} /// Node id used to represent the root of the crate. pub const CRATE_NODE_ID: NodeId = NodeId(0); diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index fb59f41110670..8c8b4173fe588 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -138,8 +138,8 @@ pub struct SpanLabel { pub label: Option, } -impl Encodable for Span { - fn encode(&self, s: &mut S) -> Result<(), S::Error> { +impl serialize::UseSpecializedEncodable for Span { + fn default_encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_struct("Span", 2, |s| { s.emit_struct_field("lo", 0, |s| { self.lo.encode(s) @@ -152,7 +152,15 @@ impl Encodable for Span { } } -impl serialize::UseSpecializedDecodable for Span {} +impl serialize::UseSpecializedDecodable for Span { + fn default_decode(d: &mut D) -> Result { + d.read_struct("Span", 2, |d| { + let lo = d.read_struct_field("lo", 0, Decodable::decode)?; + let hi = d.read_struct_field("hi", 1, Decodable::decode)?; + Ok(mk_sp(lo, hi)) + }) + } +} fn default_span_debug(span: Span, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Span {{ lo: {:?}, hi: {:?}, expn_id: {:?} }}", From a23b8cafeceb0560c58332cd9a0deb2357778ad1 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Sun, 18 Sep 2016 11:12:29 +0300 Subject: [PATCH 34/39] rustc: don't hash the --extern crate name, but the original one, in DefPath. --- src/librustc/hir/map/definitions.rs | 8 ++------ src/librustc/ty/context.rs | 8 ++++++++ src/librustc/ty/item_path.rs | 6 +----- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index af751e51d931e..f404f60cc9cef 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -115,11 +115,7 @@ impl DefPath { pub fn to_string(&self, tcx: TyCtxt) -> String { let mut s = String::with_capacity(self.data.len() * 16); - if self.krate == LOCAL_CRATE { - s.push_str(&tcx.crate_name(self.krate)); - } else { - s.push_str(&tcx.sess.cstore.original_crate_name(self.krate)); - } + s.push_str(&tcx.original_crate_name(self.krate)); s.push_str("/"); s.push_str(&tcx.crate_disambiguator(self.krate)); @@ -141,7 +137,7 @@ impl DefPath { } pub fn deterministic_hash_to(&self, tcx: TyCtxt, state: &mut H) { - tcx.crate_name(self.krate).hash(state); + tcx.original_crate_name(self.krate).hash(state); tcx.crate_disambiguator(self.krate).hash(state); self.data.hash(state); } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 0faf6750abd97..d5e5f4402bb85 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -513,6 +513,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } + pub fn original_crate_name(self, cnum: CrateNum) -> token::InternedString { + if cnum == LOCAL_CRATE { + self.crate_name.clone() + } else { + self.sess.cstore.original_crate_name(cnum) + } + } + pub fn crate_disambiguator(self, cnum: CrateNum) -> token::InternedString { if cnum == LOCAL_CRATE { self.sess.local_crate_disambiguator() diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index ca12dde73b84b..fdf5185eb69e2 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -101,11 +101,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { RootMode::Absolute => { // In absolute mode, just write the crate name // unconditionally. - if cnum == LOCAL_CRATE { - buffer.push(&self.crate_name(cnum)); - } else { - buffer.push(&self.sess.cstore.original_crate_name(cnum)); - } + buffer.push(&self.original_crate_name(cnum)); } } } From 564f2ee33c479c74f68fd9ae33b179de0b8537c9 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Sun, 18 Sep 2016 14:05:49 +0300 Subject: [PATCH 35/39] rustc_metadata: don't die with --test because CFG_VERSION is missing. --- src/librustc_metadata/schema.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index 956577ed8fb89..f4d1e8e17f842 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -26,8 +26,12 @@ use syntax_pos::{self, Span}; use std::marker::PhantomData; +#[cfg(not(test))] pub const RUSTC_VERSION: &'static str = concat!("rustc ", env!("CFG_VERSION")); +#[cfg(test)] +pub const RUSTC_VERSION: &'static str = "rustc 0.0.0-unit-test"; + /// Metadata encoding version. /// NB: increment this if you change the format of metadata such that /// the rustc version can't be found to compare with `RUSTC_VERSION`. From 521d3ea19323c4c3ba18effbfee58c10b2aaf28b Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Mon, 19 Sep 2016 03:45:38 +0300 Subject: [PATCH 36/39] rustc_resolve: bring back "struct called like a function" cross-crate. --- src/librustc/middle/cstore.rs | 4 +++- src/librustc_metadata/csearch.rs | 6 ++++++ src/librustc_metadata/decoder.rs | 9 +++++++++ src/librustc_resolve/build_reduced_graph.rs | 6 +++++- src/test/compile-fail/auxiliary/issue_19452_aux.rs | 13 +++++++++++++ src/test/compile-fail/issue-19452.rs | 7 +++++++ 6 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 src/test/compile-fail/auxiliary/issue_19452_aux.rs diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 2ebf7ba6d53d2..e57e116cea740 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -200,6 +200,7 @@ pub trait CrateStore<'tcx> { -> Option; fn def_key(&self, def: DefId) -> hir_map::DefKey; fn relative_def_path(&self, def: DefId) -> Option; + fn variant_kind(&self, def_id: DefId) -> Option; fn struct_ctor_def_id(&self, struct_def_id: DefId) -> Option; fn struct_field_names(&self, def: DefId) -> Vec; fn item_children(&self, did: DefId) -> Vec; @@ -283,7 +284,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { fn stability(&self, def: DefId) -> Option { bug!("stability") } fn deprecation(&self, def: DefId) -> Option { bug!("deprecation") } fn visibility(&self, def: DefId) -> ty::Visibility { bug!("visibility") } - fn closure_kind(&self, def_id: DefId) -> ty::ClosureKind { bug!("closure_kind") } + fn closure_kind(&self, def_id: DefId) -> ty::ClosureKind { bug!("closure_kind") } fn closure_ty<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> ty::ClosureTy<'tcx> { bug!("closure_ty") } fn item_variances(&self, def: DefId) -> Vec { bug!("item_variances") } @@ -376,6 +377,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { fn relative_def_path(&self, def: DefId) -> Option { bug!("relative_def_path") } + fn variant_kind(&self, def_id: DefId) -> Option { bug!("variant_kind") } fn struct_ctor_def_id(&self, struct_def_id: DefId) -> Option { bug!("struct_ctor_def_id") } fn struct_field_names(&self, def: DefId) -> Vec { bug!("struct_field_names") } diff --git a/src/librustc_metadata/csearch.rs b/src/librustc_metadata/csearch.rs index 7013720224a64..1f25136ffe1ac 100644 --- a/src/librustc_metadata/csearch.rs +++ b/src/librustc_metadata/csearch.rs @@ -342,6 +342,12 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { self.get_crate_data(def.krate).def_path(def.index) } + fn variant_kind(&self, def_id: DefId) -> Option + { + self.dep_graph.read(DepNode::MetaData(def_id)); + self.get_crate_data(def_id.krate).get_variant_kind(def_id.index) + } + fn struct_ctor_def_id(&self, struct_def_id: DefId) -> Option { self.dep_graph.read(DepNode::MetaData(struct_def_id)); diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index e718a107bbe29..3e4a2542b270b 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -787,6 +787,15 @@ impl<'a, 'tcx> CrateMetadata { self.entry(id).variances.decode(self).collect() } + pub fn get_variant_kind(&self, node_id: DefIndex) -> Option { + match self.entry(node_id).kind { + EntryKind::Struct(data) | + EntryKind::Union(data) | + EntryKind::Variant(data) => Some(data.decode(self).kind), + _ => None + } + } + pub fn get_struct_ctor_def_id(&self, node_id: DefIndex) -> Option { match self.entry(node_id).kind { EntryKind::Struct(data) => { diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 3c5e9e6cd3a99..c9591c31831a8 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -411,12 +411,16 @@ impl<'b> Resolver<'b> { let module = self.new_module(parent_link, Some(def), None); let _ = self.try_define(parent, name, TypeNS, (module, DUMMY_SP, vis)); } - Def::Variant(..) => { + Def::Variant(variant_id) => { debug!("(building reduced graph for external crate) building variant {}", name); // Variants are always treated as importable to allow them to be glob used. // All variants are defined in both type and value namespaces as future-proofing. let _ = self.try_define(parent, name, TypeNS, (def, DUMMY_SP, vis)); let _ = self.try_define(parent, name, ValueNS, (def, DUMMY_SP, vis)); + if self.session.cstore.variant_kind(variant_id) == Some(ty::VariantKind::Struct) { + // Not adding fields for variants as they are not accessed with a self receiver + self.structs.insert(variant_id, Vec::new()); + } } Def::Fn(..) | Def::Static(..) | diff --git a/src/test/compile-fail/auxiliary/issue_19452_aux.rs b/src/test/compile-fail/auxiliary/issue_19452_aux.rs new file mode 100644 index 0000000000000..205566e4b1f54 --- /dev/null +++ b/src/test/compile-fail/auxiliary/issue_19452_aux.rs @@ -0,0 +1,13 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub enum Homura { + Madoka { age: u32 } +} diff --git a/src/test/compile-fail/issue-19452.rs b/src/test/compile-fail/issue-19452.rs index 15d5d2b80c31d..34872b7c8c503 100644 --- a/src/test/compile-fail/issue-19452.rs +++ b/src/test/compile-fail/issue-19452.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// aux-build:issue_19452_aux.rs +extern crate issue_19452_aux; + enum Homura { Madoka { age: u32 } } @@ -16,4 +19,8 @@ fn main() { let homura = Homura::Madoka; //~^ ERROR uses it like a function //~| struct called like a function + + let homura = issue_19452_aux::Homura::Madoka; + //~^ ERROR uses it like a function + //~| struct called like a function } From ade79d760905ab589851ca9e9ab3bb583e4da7c4 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Mon, 19 Sep 2016 12:47:47 +0300 Subject: [PATCH 37/39] rustc_trans: simplify vtable and symbol handling. --- src/librustc/traits/mod.rs | 84 ++++++++- src/librustc/traits/specialize/mod.rs | 39 +++- src/librustc_trans/back/symbol_names.rs | 44 ++--- src/librustc_trans/callee.rs | 29 ++- src/librustc_trans/closure.rs | 8 +- src/librustc_trans/collector.rs | 82 +++------ src/librustc_trans/common.rs | 38 ---- src/librustc_trans/meth.rs | 230 +++--------------------- 8 files changed, 199 insertions(+), 355 deletions(-) diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index a96cf1111e1d3..7ba10d9c0a58e 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -40,7 +40,7 @@ pub use self::select::{EvaluationCache, SelectionContext, SelectionCache}; pub use self::select::{MethodMatchResult, MethodMatched, MethodAmbiguous, MethodDidNotMatch}; pub use self::select::{MethodMatchedData}; // intentionally don't export variants pub use self::specialize::{OverlapError, specialization_graph, specializes, translate_substs}; -pub use self::specialize::{SpecializesCache}; +pub use self::specialize::{SpecializesCache, find_method}; pub use self::util::elaborate_predicates; pub use self::util::supertraits; pub use self::util::Supertraits; @@ -527,6 +527,88 @@ pub fn fully_normalize<'a, 'gcx, 'tcx, T>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, Ok(resolved_value) } +/// Normalizes the predicates and checks whether they hold. If this +/// returns false, then either normalize encountered an error or one +/// of the predicates did not hold. Used when creating vtables to +/// check for unsatisfiable methods. +pub fn normalize_and_test_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + predicates: Vec>) + -> bool +{ + debug!("normalize_and_test_predicates(predicates={:?})", + predicates); + + tcx.infer_ctxt(None, None, Reveal::All).enter(|infcx| { + let mut selcx = SelectionContext::new(&infcx); + let mut fulfill_cx = FulfillmentContext::new(); + let cause = ObligationCause::dummy(); + let Normalized { value: predicates, obligations } = + normalize(&mut selcx, cause.clone(), &predicates); + for obligation in obligations { + fulfill_cx.register_predicate_obligation(&infcx, obligation); + } + for predicate in predicates { + let obligation = Obligation::new(cause.clone(), predicate); + fulfill_cx.register_predicate_obligation(&infcx, obligation); + } + + fulfill_cx.select_all_or_error(&infcx).is_ok() + }) +} + +/// Given a trait `trait_ref`, iterates the vtable entries +/// that come from `trait_ref`, including its supertraits. +#[inline] // FIXME(#35870) Avoid closures being unexported due to impl Trait. +pub fn get_vtable_methods<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + trait_ref: ty::PolyTraitRef<'tcx>) + -> impl Iterator)>> + 'a +{ + debug!("get_vtable_methods({:?})", trait_ref); + + supertraits(tcx, trait_ref).flat_map(move |trait_ref| { + tcx.populate_implementations_for_trait_if_necessary(trait_ref.def_id()); + + let trait_item_def_ids = tcx.impl_or_trait_items(trait_ref.def_id()); + let trait_methods = (0..trait_item_def_ids.len()).filter_map(move |i| { + match tcx.impl_or_trait_item(trait_item_def_ids[i]) { + ty::MethodTraitItem(m) => Some(m), + _ => None + } + }); + + // Now list each method's DefId and Substs (for within its trait). + // If the method can never be called from this object, produce None. + trait_methods.map(move |trait_method| { + debug!("get_vtable_methods: trait_method={:?}", trait_method); + + // Some methods cannot be called on an object; skip those. + if !tcx.is_vtable_safe_method(trait_ref.def_id(), &trait_method) { + debug!("get_vtable_methods: not vtable safe"); + return None; + } + + // the method may have some early-bound lifetimes, add + // regions for those + let substs = Substs::for_item(tcx, trait_method.def_id, + |_, _| tcx.mk_region(ty::ReErased), + |def, _| trait_ref.substs().type_for_def(def)); + + // It's possible that the method relies on where clauses that + // do not hold for this particular set of type parameters. + // Note that this method could then never be called, so we + // do not want to try and trans it, in that case (see #23435). + let predicates = trait_method.predicates.instantiate_own(tcx, substs); + if !normalize_and_test_predicates(tcx, predicates.predicates) { + debug!("get_vtable_methods: predicates do not hold"); + return None; + } + + Some((trait_method.def_id, substs)) + }) + }) +} + impl<'tcx,O> Obligation<'tcx,O> { pub fn new(cause: ObligationCause<'tcx>, trait_ref: O) diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index 2f63526bf6c27..e37425901c8c8 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -26,9 +26,11 @@ use infer::{InferCtxt, TypeOrigin}; use middle::region; use ty::subst::{Subst, Substs}; use traits::{self, Reveal, ObligationCause, Normalized}; -use ty::{self, TyCtxt}; +use ty::{self, TyCtxt, TypeFoldable}; use syntax_pos::DUMMY_SP; +use syntax::ast; + pub mod specialization_graph; /// Information pertinent to an overlapping impl error. @@ -103,6 +105,41 @@ pub fn translate_substs<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, source_substs.rebase_onto(infcx.tcx, source_impl, target_substs) } +/// Given a selected impl described by `impl_data`, returns the +/// definition and substitions for the method with the name `name`, +/// and trait method substitutions `substs`, in that impl, a less +/// specialized impl, or the trait default, whichever applies. +pub fn find_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + name: ast::Name, + substs: &'tcx Substs<'tcx>, + impl_data: &super::VtableImplData<'tcx, ()>) + -> (DefId, &'tcx Substs<'tcx>) +{ + assert!(!substs.needs_infer()); + + let trait_def_id = tcx.trait_id_of_impl(impl_data.impl_def_id).unwrap(); + let trait_def = tcx.lookup_trait_def(trait_def_id); + + match trait_def.ancestors(impl_data.impl_def_id).fn_defs(tcx, name).next() { + Some(node_item) => { + let substs = tcx.infer_ctxt(None, None, Reveal::All).enter(|infcx| { + let substs = substs.rebase_onto(tcx, trait_def_id, impl_data.substs); + let substs = translate_substs(&infcx, impl_data.impl_def_id, + substs, node_item.node); + tcx.lift(&substs).unwrap_or_else(|| { + bug!("find_method: translate_substs \ + returned {:?} which contains inference types/regions", + substs); + }) + }); + (node_item.item.def_id, substs) + } + None => { + bug!("method {:?} not found in {:?}", name, impl_data.impl_def_id) + } + } +} + /// Is impl1 a specialization of impl2? /// /// Specialization is determined by the sets of types to which the impls apply; diff --git a/src/librustc_trans/back/symbol_names.rs b/src/librustc_trans/back/symbol_names.rs index 500e9edebf3fe..0a668db069080 100644 --- a/src/librustc_trans/back/symbol_names.rs +++ b/src/librustc_trans/back/symbol_names.rs @@ -97,7 +97,7 @@ //! virtually impossible. Thus, symbol hash generation exclusively relies on //! DefPaths which are much more robust in the face of changes to the code base. -use common::{CrateContext, SharedCrateContext, gensym_name}; +use common::SharedCrateContext; use monomorphize::Instance; use util::sha2::{Digest, Sha256}; @@ -152,16 +152,17 @@ fn get_symbol_hash<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, let mut hash_state = scx.symbol_hasher().borrow_mut(); record_time(&tcx.sess.perf_stats.symbol_hash_time, || { hash_state.reset(); + let mut hasher = Sha256Hasher(&mut hash_state); - let mut hasher = ty::util::TypeIdHasher::new(tcx, Sha256Hasher(&mut hash_state)); // the main symbol name is not necessarily unique; hash in the // compiler's internal def-path, guaranteeing each symbol has a // truly unique path - hasher.hash(def_path.to_string(tcx)); + def_path.deterministic_hash_to(tcx, &mut hasher); // Include the main item-type. Note that, in this case, the // assertions about `needs_subst` may not hold, but this item-type // ought to be the same for every reference anyway. + let mut hasher = ty::util::TypeIdHasher::new(tcx, hasher); assert!(!item_type.has_erasable_regions()); hasher.visit_ty(item_type); @@ -172,18 +173,15 @@ fn get_symbol_hash<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, substs.visit_with(&mut hasher); } }); - fn truncated_hash_result(symbol_hasher: &mut Sha256) -> String { - let output = symbol_hasher.result_bytes(); - // 64 bits should be enough to avoid collisions. - output[.. 8].to_hex() - } - format!("h{}", truncated_hash_result(&mut hash_state)) + // 64 bits should be enough to avoid collisions. + let output = hash_state.result_bytes(); + format!("h{}", output[..8].to_hex()) } impl<'a, 'tcx> Instance<'tcx> { pub fn symbol_name(self, scx: &SharedCrateContext<'a, 'tcx>) -> String { - let Instance { def: def_id, ref substs } = self; + let Instance { def: def_id, substs } = self; debug!("symbol_name(def_id={:?}, substs={:?})", def_id, substs); @@ -278,7 +276,7 @@ impl<'a, 'tcx> Instance<'tcx> { scx.tcx().push_item_path(&mut buffer, def_id); }); - mangle(buffer.names.into_iter(), Some(&hash[..])) + mangle(buffer.names.into_iter(), &hash) } } @@ -307,23 +305,7 @@ pub fn exported_name_from_type_and_prefix<'a, 'tcx>(scx: &SharedCrateContext<'a, }; let hash = get_symbol_hash(scx, &empty_def_path, t, None); let path = [token::intern_and_get_ident(prefix)]; - mangle(path.iter().cloned(), Some(&hash[..])) -} - -/// Only symbols that are invisible outside their compilation unit should use a -/// name generated by this function. -pub fn internal_name_from_type_and_suffix<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, - t: Ty<'tcx>, - suffix: &str) - -> String { - let path = [token::intern(&t.to_string()).as_str(), - gensym_name(suffix).as_str()]; - let def_path = DefPath { - data: vec![], - krate: LOCAL_CRATE, - }; - let hash = get_symbol_hash(ccx.shared(), &def_path, t, None); - mangle(path.iter().cloned(), Some(&hash[..])) + mangle(path.iter().cloned(), &hash) } // Name sanitation. LLVM will happily accept identifiers with weird names, but @@ -376,7 +358,7 @@ pub fn sanitize(s: &str) -> String { return result; } -pub fn mangle>(path: PI, hash: Option<&str>) -> String { +fn mangle>(path: PI, hash: &str) -> String { // Follow C++ namespace-mangling style, see // http://en.wikipedia.org/wiki/Name_mangling for more info. // @@ -403,9 +385,7 @@ pub fn mangle>(path: PI, hash: Option<&str>) - push(&mut n, &data); } - if let Some(s) = hash { - push(&mut n, s) - } + push(&mut n, hash); n.push('E'); // End name-sequence. n diff --git a/src/librustc_trans/callee.rs b/src/librustc_trans/callee.rs index 9785ee2455793..8822287a0e754 100644 --- a/src/librustc_trans/callee.rs +++ b/src/librustc_trans/callee.rs @@ -17,7 +17,6 @@ pub use self::CalleeData::*; use arena::TypedArena; -use back::symbol_names; use llvm::{self, ValueRef, get_params}; use rustc::hir::def_id::DefId; use rustc::ty::subst::Substs; @@ -133,26 +132,25 @@ impl<'tcx> Callee<'tcx> { let trait_ref = tcx.normalize_associated_type(&ty::Binder(trait_ref)); match common::fulfill_obligation(ccx.shared(), DUMMY_SP, trait_ref) { traits::VtableImpl(vtable_impl) => { - let impl_did = vtable_impl.impl_def_id; - let mname = tcx.item_name(def_id); - // create a concatenated set of substitutions which includes - // those from the impl and those from the method: - let mth = meth::get_impl_method(tcx, substs, impl_did, vtable_impl.substs, mname); + let name = tcx.item_name(def_id); + let (def_id, substs) = traits::find_method(tcx, name, substs, &vtable_impl); // Translate the function, bypassing Callee::def. // That is because default methods have the same ID as the // trait method used to look up the impl method that ended // up here, so calling Callee::def would infinitely recurse. - let (llfn, ty) = get_fn(ccx, mth.method.def_id, mth.substs); + let (llfn, ty) = get_fn(ccx, def_id, substs); Callee::ptr(llfn, ty) } traits::VtableClosure(vtable_closure) => { // The substitutions should have no type parameters remaining // after passing through fulfill_obligation let trait_closure_kind = tcx.lang_items.fn_trait_kind(trait_id).unwrap(); + let instance = Instance::new(def_id, substs); let llfn = closure::trans_closure_method(ccx, vtable_closure.closure_def_id, vtable_closure.substs, + instance, trait_closure_kind); let method_ty = def_ty(ccx.shared(), def_id, substs); @@ -160,7 +158,10 @@ impl<'tcx> Callee<'tcx> { } traits::VtableFnPointer(vtable_fn_pointer) => { let trait_closure_kind = tcx.lang_items.fn_trait_kind(trait_id).unwrap(); - let llfn = trans_fn_pointer_shim(ccx, trait_closure_kind, vtable_fn_pointer.fn_ty); + let instance = Instance::new(def_id, substs); + let llfn = trans_fn_pointer_shim(ccx, instance, + trait_closure_kind, + vtable_fn_pointer.fn_ty); let method_ty = def_ty(ccx.shared(), def_id, substs); Callee::ptr(llfn, method_ty) @@ -217,9 +218,7 @@ impl<'tcx> Callee<'tcx> { pub fn reify<'a>(self, ccx: &CrateContext<'a, 'tcx>) -> ValueRef { match self.data { Fn(llfn) => llfn, - Virtual(idx) => { - meth::trans_object_shim(ccx, self.ty, idx) - } + Virtual(_) => meth::trans_object_shim(ccx, self), NamedTupleConstructor(disr) => match self.ty.sty { ty::TyFnDef(def_id, substs, _) => { let instance = Instance::new(def_id, substs); @@ -264,8 +263,9 @@ fn def_ty<'a, 'tcx>(shared: &SharedCrateContext<'a, 'tcx>, /// ``` /// /// but for the bare function type given. -pub fn trans_fn_pointer_shim<'a, 'tcx>( +fn trans_fn_pointer_shim<'a, 'tcx>( ccx: &'a CrateContext<'a, 'tcx>, + method_instance: Instance<'tcx>, closure_kind: ty::ClosureKind, bare_fn_ty: Ty<'tcx>) -> ValueRef @@ -345,10 +345,7 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>( debug!("tuple_fn_ty: {:?}", tuple_fn_ty); // - let function_name = - symbol_names::internal_name_from_type_and_suffix(ccx, - bare_fn_ty, - "fn_pointer_shim"); + let function_name = method_instance.symbol_name(ccx.shared()); let llfn = declare::define_internal_fn(ccx, &function_name, tuple_fn_ty); attributes::set_frame_pointer_elimination(ccx, llfn); // diff --git a/src/librustc_trans/closure.rs b/src/librustc_trans/closure.rs index 83882c27e8e7b..c0692e8085fc2 100644 --- a/src/librustc_trans/closure.rs +++ b/src/librustc_trans/closure.rs @@ -9,7 +9,6 @@ // except according to those terms. use arena::TypedArena; -use back::symbol_names; use llvm::{self, ValueRef, get_params}; use rustc::hir::def_id::DefId; use abi::{Abi, FnType}; @@ -152,6 +151,7 @@ pub fn trans_closure_body_via_mir<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, pub fn trans_closure_method<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>, closure_def_id: DefId, substs: ty::ClosureSubsts<'tcx>, + method_instance: Instance<'tcx>, trait_closure_kind: ty::ClosureKind) -> ValueRef { @@ -199,7 +199,7 @@ pub fn trans_closure_method<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>, // fn call_once(mut self, ...) { call_mut(&mut self, ...) } // // These are both the same at trans time. - trans_fn_once_adapter_shim(ccx, closure_def_id, substs, llfn) + trans_fn_once_adapter_shim(ccx, closure_def_id, substs, method_instance, llfn) } _ => { bug!("trans_closure_adapter_shim: cannot convert {:?} to {:?}", @@ -213,6 +213,7 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>( ccx: &'a CrateContext<'a, 'tcx>, closure_def_id: DefId, substs: ty::ClosureSubsts<'tcx>, + method_instance: Instance<'tcx>, llreffn: ValueRef) -> ValueRef { @@ -255,8 +256,7 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>( })); // Create the by-value helper. - let function_name = - symbol_names::internal_name_from_type_and_suffix(ccx, llonce_fn_ty, "once_shim"); + let function_name = method_instance.symbol_name(ccx.shared()); let lloncefn = declare::declare_fn(ccx, &function_name, llonce_fn_ty); attributes::set_frame_pointer_elimination(ccx, lloncefn); diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index b9449eeecf427..2849b384e1bd2 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -210,9 +210,8 @@ use errors; use syntax_pos::DUMMY_SP; use base::custom_coerce_unsize_info; use context::SharedCrateContext; -use common::{fulfill_obligation, normalize_and_test_predicates, type_is_sized}; +use common::{fulfill_obligation, type_is_sized}; use glue::{self, DropGlueKind}; -use meth; use monomorphize::{self, Instance}; use util::nodemap::{FnvHashSet, FnvHashMap, DefIdMap}; @@ -899,17 +898,8 @@ fn do_static_trait_method_dispatch<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, // Now that we know which impl is being used, we can dispatch to // the actual function: match vtbl { - traits::VtableImpl(traits::VtableImplData { - impl_def_id: impl_did, - substs: impl_substs, - nested: _ }) => - { - let impl_method = meth::get_impl_method(tcx, - rcvr_substs, - impl_did, - impl_substs, - trait_method.name); - Some((impl_method.method.def_id, &impl_method.substs)) + traits::VtableImpl(impl_data) => { + Some(traits::find_method(tcx, trait_method.name, rcvr_substs, &impl_data)) } // If we have a closure or a function pointer, we will also encounter // the concrete closure/function somewhere else (during closure or fn @@ -1043,43 +1033,19 @@ fn create_trans_items_for_vtable_methods<'a, 'tcx>(scx: &SharedCrateContext<'a, if let ty::TyTrait(ref trait_ty) = trait_ty.sty { let poly_trait_ref = trait_ty.principal.with_self_ty(scx.tcx(), impl_ty); + let param_substs = Substs::empty(scx.tcx()); // Walk all methods of the trait, including those of its supertraits - for trait_ref in traits::supertraits(scx.tcx(), poly_trait_ref) { - let vtable = fulfill_obligation(scx, DUMMY_SP, trait_ref); - match vtable { - traits::VtableImpl( - traits::VtableImplData { - impl_def_id, - substs, - nested: _ }) => { - let items = meth::get_vtable_methods(scx.tcx(), impl_def_id, substs) - .into_iter() - // filter out None values - .filter_map(|opt_impl_method| opt_impl_method) - // create translation items - .filter_map(|impl_method| { - if can_have_local_instance(scx.tcx(), impl_method.method.def_id) { - Some(create_fn_trans_item(scx, - impl_method.method.def_id, - impl_method.substs, - Substs::empty(scx.tcx()))) - } else { - None - } - }); - - output.extend(items); - } - _ => { /* */ } - } - } + let methods = traits::get_vtable_methods(scx.tcx(), poly_trait_ref); + let methods = methods.filter_map(|method| method) + .filter_map(|(def_id, substs)| do_static_dispatch(scx, def_id, substs, param_substs)) + .filter(|&(def_id, _)| can_have_local_instance(scx.tcx(), def_id)) + .map(|(def_id, substs)| create_fn_trans_item(scx, def_id, substs, param_substs)); + output.extend(methods); // Also add the destructor let dg_type = glue::get_drop_glue_type(scx.tcx(), impl_ty); - if glue::type_needs_drop(scx.tcx(), dg_type) { - output.push(TransItem::DropGlue(DropGlueKind::Ty(dg_type))); - } + output.push(TransItem::DropGlue(DropGlueKind::Ty(dg_type))); } } @@ -1239,25 +1205,27 @@ fn create_trans_items_for_default_impls<'a, 'tcx>(scx: &SharedCrateContext<'a, ' let impl_substs = Substs::for_item(tcx, impl_def_id, |_, _| tcx.mk_region(ty::ReErased), |_, _| tcx.types.err); - let mth = meth::get_impl_method(tcx, - callee_substs, - impl_def_id, - impl_substs, - method.name); - - assert!(mth.is_provided); - - let predicates = mth.method.predicates.predicates.subst(tcx, &mth.substs); - if !normalize_and_test_predicates(tcx, predicates) { + let impl_data = traits::VtableImplData { + impl_def_id: impl_def_id, + substs: impl_substs, + nested: vec![] + }; + let (def_id, substs) = traits::find_method(tcx, + method.name, + callee_substs, + &impl_data); + + let predicates = tcx.lookup_predicates(def_id).predicates + .subst(tcx, substs); + if !traits::normalize_and_test_predicates(tcx, predicates) { continue; } if can_have_local_instance(tcx, method.def_id) { - let empty_substs = tcx.erase_regions(&mth.substs); let item = create_fn_trans_item(scx, method.def_id, callee_substs, - empty_substs); + tcx.erase_regions(&substs)); output.push(item); } } diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs index e0de04d150ca7..db1a541919036 100644 --- a/src/librustc_trans/common.rs +++ b/src/librustc_trans/common.rs @@ -150,15 +150,6 @@ pub fn type_is_zero_size<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) - llsize_of_alloc(ccx, llty) == 0 } -/// Generates a unique symbol based off the name given. This is used to create -/// unique symbols for things like closures. -pub fn gensym_name(name: &str) -> ast::Name { - let num = token::gensym(name).0; - // use one colon which will get translated to a period by the mangler, and - // we're guaranteed that `num` is globally unique for this crate. - token::gensym(&format!("{}:{}", name, num)) -} - /* * A note on nomenclature of linking: "extern", "foreign", and "upcall". * @@ -1002,35 +993,6 @@ pub fn fulfill_obligation<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, }) } -/// Normalizes the predicates and checks whether they hold. If this -/// returns false, then either normalize encountered an error or one -/// of the predicates did not hold. Used when creating vtables to -/// check for unsatisfiable methods. -pub fn normalize_and_test_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - predicates: Vec>) - -> bool -{ - debug!("normalize_and_test_predicates(predicates={:?})", - predicates); - - tcx.infer_ctxt(None, None, Reveal::All).enter(|infcx| { - let mut selcx = SelectionContext::new(&infcx); - let mut fulfill_cx = traits::FulfillmentContext::new(); - let cause = traits::ObligationCause::dummy(); - let traits::Normalized { value: predicates, obligations } = - traits::normalize(&mut selcx, cause.clone(), &predicates); - for obligation in obligations { - fulfill_cx.register_predicate_obligation(&infcx, obligation); - } - for predicate in predicates { - let obligation = traits::Obligation::new(cause.clone(), predicate); - fulfill_cx.register_predicate_obligation(&infcx, obligation); - } - - fulfill_cx.select_all_or_error(&infcx).is_ok() - }) -} - pub fn langcall(tcx: TyCtxt, span: Option, msg: &str, diff --git a/src/librustc_trans/meth.rs b/src/librustc_trans/meth.rs index 8540c7a99db15..e8dcaf71f2dd2 100644 --- a/src/librustc_trans/meth.rs +++ b/src/librustc_trans/meth.rs @@ -8,33 +8,25 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::rc::Rc; - use attributes; use arena::TypedArena; -use back::symbol_names; use llvm::{ValueRef, get_params}; -use rustc::hir::def_id::DefId; -use rustc::ty::subst::{Subst, Substs}; -use rustc::traits::{self, Reveal}; +use rustc::traits; use abi::FnType; use base::*; use build::*; -use callee::{Callee, Virtual, trans_fn_pointer_shim}; -use closure; +use callee::Callee; use common::*; use consts; use debuginfo::DebugLoc; use declare; use glue; use machine; +use monomorphize::Instance; use type_::Type; use type_of::*; use value::Value; -use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; - -use syntax::ast::Name; -use syntax_pos::DUMMY_SP; +use rustc::ty; // drop_glue pointer, size, align. const VTABLE_OFFSET: usize = 3; @@ -73,23 +65,26 @@ pub fn get_virtual_method<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, /// In fact, all virtual calls can be thought of as normal trait calls /// that go through this shim function. pub fn trans_object_shim<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>, - method_ty: Ty<'tcx>, - vtable_index: usize) + callee: Callee<'tcx>) -> ValueRef { let _icx = push_ctxt("trans_object_shim"); let tcx = ccx.tcx(); - debug!("trans_object_shim(vtable_index={}, method_ty={:?})", - vtable_index, - method_ty); + debug!("trans_object_shim({:?})", callee); + + let (sig, abi, function_name) = match callee.ty.sty { + ty::TyFnDef(def_id, substs, f) => { + let instance = Instance::new(def_id, substs); + (&f.sig, f.abi, instance.symbol_name(ccx.shared())) + } + _ => bug!() + }; - let sig = tcx.erase_late_bound_regions(&method_ty.fn_sig()); + let sig = tcx.erase_late_bound_regions(sig); let sig = tcx.normalize_associated_type(&sig); - let fn_ty = FnType::new(ccx, method_ty.fn_abi(), &sig, &[]); + let fn_ty = FnType::new(ccx, abi, &sig, &[]); - let function_name = - symbol_names::internal_name_from_type_and_suffix(ccx, method_ty, "object_shim"); - let llfn = declare::define_internal_fn(ccx, &function_name, method_ty); + let llfn = declare::define_internal_fn(ccx, &function_name, callee.ty); attributes::set_frame_pointer_elimination(ccx, llfn); let (block_arena, fcx): (TypedArena<_>, FunctionContext); @@ -98,16 +93,7 @@ pub fn trans_object_shim<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>, let mut bcx = fcx.init(false); let dest = fcx.llretslotptr.get(); - - debug!("trans_object_shim: method_offset_in_vtable={}", - vtable_index); - let llargs = get_params(fcx.llfn); - - let callee = Callee { - data: Virtual(vtable_index), - ty: method_ty - }; bcx = callee.call(bcx, DebugLoc::None, &llargs[fcx.fn_ty.ret.is_indirect() as usize..], dest).bcx; @@ -140,72 +126,23 @@ pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, } // Not in the cache. Build it. - let methods = traits::supertraits(tcx, trait_ref.clone()).flat_map(|trait_ref| { - let vtable = fulfill_obligation(ccx.shared(), DUMMY_SP, trait_ref.clone()); - match vtable { - // Should default trait error here? - traits::VtableDefaultImpl(_) | - traits::VtableBuiltin(_) => { - Vec::new().into_iter() - } - traits::VtableImpl( - traits::VtableImplData { - impl_def_id: id, - substs, - nested: _ }) => { - let nullptr = C_null(Type::nil(ccx).ptr_to()); - get_vtable_methods(tcx, id, substs) - .into_iter() - .map(|opt_mth| opt_mth.map_or(nullptr, |mth| { - Callee::def(ccx, mth.method.def_id, &mth.substs).reify(ccx) - })) - .collect::>() - .into_iter() - } - traits::VtableClosure( - traits::VtableClosureData { - closure_def_id, - substs, - nested: _ }) => { - let trait_closure_kind = tcx.lang_items.fn_trait_kind(trait_ref.def_id()).unwrap(); - let llfn = closure::trans_closure_method(ccx, - closure_def_id, - substs, - trait_closure_kind); - vec![llfn].into_iter() - } - traits::VtableFnPointer( - traits::VtableFnPointerData { - fn_ty: bare_fn_ty, - nested: _ }) => { - let trait_closure_kind = tcx.lang_items.fn_trait_kind(trait_ref.def_id()).unwrap(); - vec![trans_fn_pointer_shim(ccx, trait_closure_kind, bare_fn_ty)].into_iter() - } - traits::VtableObject(ref data) => { - // this would imply that the Self type being erased is - // an object type; this cannot happen because we - // cannot cast an unsized type into a trait object - bug!("cannot get vtable for an object type: {:?}", - data); - } - traits::VtableParam(..) => { - bug!("resolved vtable for {:?} to bad vtable {:?} in trans", - trait_ref, - vtable); - } - } + let nullptr = C_null(Type::nil(ccx).ptr_to()); + let methods = traits::get_vtable_methods(tcx, trait_ref).map(|opt_mth| { + opt_mth.map_or(nullptr, |(def_id, substs)| { + Callee::def(ccx, def_id, substs).reify(ccx) + }) }); let size_ty = sizing_type_of(ccx, trait_ref.self_ty()); let size = machine::llsize_of_alloc(ccx, size_ty); let align = align_of(ccx, trait_ref.self_ty()); - let components: Vec<_> = vec![ + let components: Vec<_> = [ // Generate a destructor for the vtable. glue::get_drop_glue(ccx, trait_ref.self_ty()), C_uint(ccx, size), C_uint(ccx, align) - ].into_iter().chain(methods).collect(); + ].iter().cloned().chain(methods).collect(); let vtable_const = C_struct(ccx, &components, false); let align = machine::llalign_of_pref(ccx, val_ty(vtable_const)); @@ -214,122 +151,3 @@ pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ccx.vtables().borrow_mut().insert(trait_ref, vtable); vtable } - -pub fn get_vtable_methods<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - impl_id: DefId, - substs: &'tcx Substs<'tcx>) - -> Vec>> -{ - debug!("get_vtable_methods(impl_id={:?}, substs={:?}", impl_id, substs); - - let trait_id = match tcx.impl_trait_ref(impl_id) { - Some(t_id) => t_id.def_id, - None => bug!("make_impl_vtable: don't know how to \ - make a vtable for a type impl!") - }; - - tcx.populate_implementations_for_trait_if_necessary(trait_id); - - let trait_item_def_ids = tcx.impl_or_trait_items(trait_id); - trait_item_def_ids - .iter() - - // Filter out non-method items. - .filter_map(|&item_def_id| { - match tcx.impl_or_trait_item(item_def_id) { - ty::MethodTraitItem(m) => Some(m), - _ => None - } - }) - - // Now produce pointers for each remaining method. If the - // method could never be called from this object, just supply - // null. - .map(|trait_method_type| { - debug!("get_vtable_methods: trait_method_def_id={:?}", - trait_method_type.def_id); - - let name = trait_method_type.name; - - // Some methods cannot be called on an object; skip those. - if !tcx.is_vtable_safe_method(trait_id, &trait_method_type) { - debug!("get_vtable_methods: not vtable safe"); - return None; - } - - debug!("get_vtable_methods: trait_method_type={:?}", - trait_method_type); - - // the method may have some early-bound lifetimes, add - // regions for those - let method_substs = Substs::for_item(tcx, trait_method_type.def_id, - |_, _| tcx.mk_region(ty::ReErased), - |_, _| tcx.types.err); - - // The substitutions we have are on the impl, so we grab - // the method type from the impl to substitute into. - let mth = get_impl_method(tcx, method_substs, impl_id, substs, name); - - debug!("get_vtable_methods: mth={:?}", mth); - - // If this is a default method, it's possible that it - // relies on where clauses that do not hold for this - // particular set of type parameters. Note that this - // method could then never be called, so we do not want to - // try and trans it, in that case. Issue #23435. - if mth.is_provided { - let predicates = mth.method.predicates.predicates.subst(tcx, &mth.substs); - if !normalize_and_test_predicates(tcx, predicates) { - debug!("get_vtable_methods: predicates do not hold"); - return None; - } - } - - Some(mth) - }) - .collect() -} - -#[derive(Debug)] -pub struct ImplMethod<'tcx> { - pub method: Rc>, - pub substs: &'tcx Substs<'tcx>, - pub is_provided: bool -} - -/// Locates the applicable definition of a method, given its name. -pub fn get_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - substs: &'tcx Substs<'tcx>, - impl_def_id: DefId, - impl_substs: &'tcx Substs<'tcx>, - name: Name) - -> ImplMethod<'tcx> -{ - assert!(!substs.needs_infer()); - - let trait_def_id = tcx.trait_id_of_impl(impl_def_id).unwrap(); - let trait_def = tcx.lookup_trait_def(trait_def_id); - - match trait_def.ancestors(impl_def_id).fn_defs(tcx, name).next() { - Some(node_item) => { - let substs = tcx.infer_ctxt(None, None, Reveal::All).enter(|infcx| { - let substs = substs.rebase_onto(tcx, trait_def_id, impl_substs); - let substs = traits::translate_substs(&infcx, impl_def_id, - substs, node_item.node); - tcx.lift(&substs).unwrap_or_else(|| { - bug!("trans::meth::get_impl_method: translate_substs \ - returned {:?} which contains inference types/regions", - substs); - }) - }); - ImplMethod { - method: node_item.item, - substs: substs, - is_provided: node_item.node.is_from_trait(), - } - } - None => { - bug!("method {:?} not found in {:?}", name, impl_def_id) - } - } -} From a2726f4a548f77f0443701c457f9f7628b5c6b6c Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Mon, 19 Sep 2016 12:37:12 +0300 Subject: [PATCH 38/39] rustc: allow less and handle fn pointers in the type hashing algorithm. --- src/librustc/ty/util.rs | 15 +++++++++------ src/librustc_trans/glue.rs | 2 ++ src/test/run-pass/typeid-intrinsic.rs | 4 ++++ 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 5c71f348b9925..d834a7d485a38 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -436,17 +436,18 @@ impl<'a, 'gcx, 'tcx, H: Hasher> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tc TyInt(i) => self.hash(i), TyUint(u) => self.hash(u), TyFloat(f) => self.hash(f), - TyAdt(d, _) => self.def_id(d.did), TyArray(_, n) => self.hash(n), TyRawPtr(m) | TyRef(_, m) => self.hash(m.mutbl), TyClosure(def_id, _) | TyAnon(def_id, _) | TyFnDef(def_id, ..) => self.def_id(def_id), + TyAdt(d, _) => self.def_id(d.did), TyFnPtr(f) => { self.hash(f.unsafety); self.hash(f.abi); self.hash(f.sig.variadic()); + self.hash(f.sig.inputs().skip_binder().len()); } TyTrait(ref data) => { self.def_id(data.principal.def_id()); @@ -468,9 +469,10 @@ impl<'a, 'gcx, 'tcx, H: Hasher> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tc TyChar | TyStr | TyBox(_) | - TySlice(_) | - TyError => {} - TyInfer(_) => bug!() + TySlice(_) => {} + + TyError | + TyInfer(_) => bug!("TypeIdHasher: unexpected type {}", ty) } ty.super_visit_with(self) @@ -478,7 +480,7 @@ impl<'a, 'gcx, 'tcx, H: Hasher> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tc fn visit_region(&mut self, r: &'tcx ty::Region) -> bool { match *r { - ty::ReStatic | ty::ReErased => { + ty::ReErased => { self.hash::(0); } ty::ReLateBound(db, ty::BrAnon(i)) => { @@ -486,6 +488,7 @@ impl<'a, 'gcx, 'tcx, H: Hasher> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tc self.hash::(db.depth); self.hash(i); } + ty::ReStatic | ty::ReEmpty | ty::ReEarlyBound(..) | ty::ReLateBound(..) | @@ -493,7 +496,7 @@ impl<'a, 'gcx, 'tcx, H: Hasher> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tc ty::ReScope(..) | ty::ReVar(..) | ty::ReSkolemized(..) => { - bug!("unexpected region found when hashing a type") + bug!("TypeIdHasher: unexpected region {:?}", r) } } false diff --git a/src/librustc_trans/glue.rs b/src/librustc_trans/glue.rs index 3073b1dbfaeeb..7b01227987222 100644 --- a/src/librustc_trans/glue.rs +++ b/src/librustc_trans/glue.rs @@ -92,6 +92,8 @@ pub fn get_drop_glue_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, t: Ty<'tcx>) -> Ty<'tcx> { assert!(t.is_normalized_for_trans()); + let t = tcx.erase_regions(&t); + // Even if there is no dtor for t, there might be one deeper down and we // might need to pass in the vtable ptr. if !type_is_sized(tcx, t) { diff --git a/src/test/run-pass/typeid-intrinsic.rs b/src/test/run-pass/typeid-intrinsic.rs index 36650368d57be..54d5415a5539b 100644 --- a/src/test/run-pass/typeid-intrinsic.rs +++ b/src/test/run-pass/typeid-intrinsic.rs @@ -87,4 +87,8 @@ pub fn main() { assert_eq!(other1::id_u32_iterator(), other2::id_u32_iterator()); assert!(other1::id_i32_iterator() != other1::id_u32_iterator()); assert!(TypeId::of::() != TypeId::of::()); + + // Check fn pointer against collisions + assert!(TypeId::of:: A) -> A>() != + TypeId::of:: A, A) -> A>()); } From 4ac30013c3402d9349f83888a9d0903f0a68746e Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Mon, 19 Sep 2016 04:26:38 +0300 Subject: [PATCH 39/39] rustc_trans: don't do on-demand drop glue instantiation. --- src/librustc_trans/glue.rs | 20 ++----------------- .../instantiation-through-vtable.rs | 1 + .../codegen-units/item-collection/unsizing.rs | 1 + .../partitioning/vtable-through-const.rs | 1 + 4 files changed, 5 insertions(+), 18 deletions(-) diff --git a/src/librustc_trans/glue.rs b/src/librustc_trans/glue.rs index 7b01227987222..2a20728f09bea 100644 --- a/src/librustc_trans/glue.rs +++ b/src/librustc_trans/glue.rs @@ -216,30 +216,14 @@ fn get_drop_glue_core<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, g: DropGlueKind<'tcx>) -> ValueRef { let g = g.map_ty(|t| get_drop_glue_type(ccx.tcx(), t)); match ccx.drop_glues().borrow().get(&g) { - Some(&(glue, _)) => return glue, + Some(&(glue, _)) => glue, None => { - debug!("Could not find drop glue for {:?} -- {} -- {}. \ - Falling back to on-demand instantiation.", + bug!("Could not find drop glue for {:?} -- {} -- {}.", g, TransItem::DropGlue(g).to_raw_string(), ccx.codegen_unit().name()); } } - - // FIXME: #34151 - // Normally, getting here would indicate a bug in trans::collector, - // since it seems to have missed a translation item. When we are - // translating with non-MIR-based trans, however, the results of the - // collector are not entirely reliable since it bases its analysis - // on MIR. Thus, we'll instantiate the missing function on demand in - // this codegen unit, so that things keep working. - - TransItem::DropGlue(g).predefine(ccx, llvm::InternalLinkage); - TransItem::DropGlue(g).define(ccx); - - // Now that we made sure that the glue function is in ccx.drop_glues, - // give it another try - get_drop_glue_core(ccx, g) } pub fn implement_drop_glue<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, diff --git a/src/test/codegen-units/item-collection/instantiation-through-vtable.rs b/src/test/codegen-units/item-collection/instantiation-through-vtable.rs index b772525122001..ad466671cf79b 100644 --- a/src/test/codegen-units/item-collection/instantiation-through-vtable.rs +++ b/src/test/codegen-units/item-collection/instantiation-through-vtable.rs @@ -31,6 +31,7 @@ impl Trait for Struct { fn main() { let s1 = Struct { _a: 0u32 }; + //~ TRANS_ITEM drop-glue i8 //~ TRANS_ITEM fn instantiation_through_vtable::{{impl}}[0]::foo[0] //~ TRANS_ITEM fn instantiation_through_vtable::{{impl}}[0]::bar[0] let _ = &s1 as &Trait; diff --git a/src/test/codegen-units/item-collection/unsizing.rs b/src/test/codegen-units/item-collection/unsizing.rs index 45ba441bc8ba6..cd4cc258f7a68 100644 --- a/src/test/codegen-units/item-collection/unsizing.rs +++ b/src/test/codegen-units/item-collection/unsizing.rs @@ -57,6 +57,7 @@ fn main() { // simple case let bool_sized = &true; + //~ TRANS_ITEM drop-glue i8 //~ TRANS_ITEM fn unsizing::{{impl}}[0]::foo[0] let _bool_unsized = bool_sized as &Trait; diff --git a/src/test/codegen-units/partitioning/vtable-through-const.rs b/src/test/codegen-units/partitioning/vtable-through-const.rs index ee5e97cd9c212..0007eaae28971 100644 --- a/src/test/codegen-units/partitioning/vtable-through-const.rs +++ b/src/test/codegen-units/partitioning/vtable-through-const.rs @@ -69,6 +69,7 @@ mod mod1 { //~ TRANS_ITEM fn vtable_through_const::main[0] @@ vtable_through_const[External] fn main() { + //~ TRANS_ITEM drop-glue i8 @@ vtable_through_const[Internal] // Since Trait1::do_something() is instantiated via its default implementation, // it is considered a generic and is instantiated here only because it is