Auto merge of #37382 - jonathandturner:rollup, r=jonathandturner

Rollup of 7 pull requests

- Successful merges: #37228, #37304, #37324, #37328, #37336, #37349, #37372
- Failed merges:
This commit is contained in:
bors 2016-10-24 16:47:38 -07:00 committed by GitHub
commit 7a208648da
24 changed files with 553 additions and 598 deletions

View File

@ -69,7 +69,7 @@ foo(&counted);
All weve done is wrap our `String` in an `Rc<T>`. But we can now pass the
`Rc<String>` around anywhere wed have a `String`. The signature of `foo`
didnt change, but works just as well with either type. This example has two
conversions: `Rc<String>` to `String` and then `String` to `&str`. Rust will do
conversions: `&Rc<String>` to `&String` and then `&String` to `&str`. Rust will do
this as many times as possible until the types match.
Another very common implementation provided by the standard library is:

View File

@ -445,8 +445,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
let mut err = struct_span_err!(self.tcx.sess, span, E0277,
"the trait bound `{}` is not satisfied",
trait_ref.to_predicate());
err.span_label(span, &format!("trait `{}` not satisfied",
trait_ref.to_predicate()));
err.span_label(span, &format!("the trait `{}` is not implemented \
for `{}`",
trait_ref,
trait_ref.self_ty()));
// Try to report a help message

View File

@ -392,27 +392,30 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
}
}
// When hashing a type this ends up affecting properties like symbol names. We
// want these symbol names to be calculated independent of other factors like
// what architecture you're compiling *from*.
//
// The hashing just uses the standard `Hash` trait, but the implementations of
// `Hash` for the `usize` and `isize` types are *not* architecture independent
// (e.g. they has 4 or 8 bytes). As a result we want to avoid `usize` and
// `isize` completely when hashing. To ensure that these don't leak in we use a
// custom hasher implementation here which inflates the size of these to a `u64`
// and `i64`.
struct WidenUsizeHasher<H> {
/// When hashing a type this ends up affecting properties like symbol names. We
/// want these symbol names to be calculated independent of other factors like
/// what architecture you're compiling *from*.
///
/// The hashing just uses the standard `Hash` trait, but the implementations of
/// `Hash` for the `usize` and `isize` types are *not* architecture independent
/// (e.g. they has 4 or 8 bytes). As a result we want to avoid `usize` and
/// `isize` completely when hashing. To ensure that these don't leak in we use a
/// custom hasher implementation here which inflates the size of these to a `u64`
/// and `i64`.
///
/// The same goes for endianess: We always convert multi-byte integers to little
/// endian before hashing.
pub struct ArchIndependentHasher<H> {
inner: H,
}
impl<H> WidenUsizeHasher<H> {
fn new(inner: H) -> WidenUsizeHasher<H> {
WidenUsizeHasher { inner: inner }
impl<H> ArchIndependentHasher<H> {
pub fn new(inner: H) -> ArchIndependentHasher<H> {
ArchIndependentHasher { inner: inner }
}
}
impl<H: Hasher> Hasher for WidenUsizeHasher<H> {
impl<H: Hasher> Hasher for ArchIndependentHasher<H> {
fn write(&mut self, bytes: &[u8]) {
self.inner.write(bytes)
}
@ -425,44 +428,44 @@ impl<H: Hasher> Hasher for WidenUsizeHasher<H> {
self.inner.write_u8(i)
}
fn write_u16(&mut self, i: u16) {
self.inner.write_u16(i)
self.inner.write_u16(i.to_le())
}
fn write_u32(&mut self, i: u32) {
self.inner.write_u32(i)
self.inner.write_u32(i.to_le())
}
fn write_u64(&mut self, i: u64) {
self.inner.write_u64(i)
self.inner.write_u64(i.to_le())
}
fn write_usize(&mut self, i: usize) {
self.inner.write_u64(i as u64)
self.inner.write_u64((i as u64).to_le())
}
fn write_i8(&mut self, i: i8) {
self.inner.write_i8(i)
}
fn write_i16(&mut self, i: i16) {
self.inner.write_i16(i)
self.inner.write_i16(i.to_le())
}
fn write_i32(&mut self, i: i32) {
self.inner.write_i32(i)
self.inner.write_i32(i.to_le())
}
fn write_i64(&mut self, i: i64) {
self.inner.write_i64(i)
self.inner.write_i64(i.to_le())
}
fn write_isize(&mut self, i: isize) {
self.inner.write_i64(i as i64)
self.inner.write_i64((i as i64).to_le())
}
}
pub struct TypeIdHasher<'a, 'gcx: 'a+'tcx, 'tcx: 'a, H> {
tcx: TyCtxt<'a, 'gcx, 'tcx>,
state: WidenUsizeHasher<H>,
state: ArchIndependentHasher<H>,
}
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: WidenUsizeHasher::new(state),
state: ArchIndependentHasher::new(state),
}
}
@ -493,6 +496,10 @@ impl<'a, 'gcx, 'tcx, H: Hasher> TypeIdHasher<'a, 'gcx, 'tcx, H> {
pub fn def_path(&mut self, def_path: &ast_map::DefPath) {
def_path.deterministic_hash_to(self.tcx, &mut self.state);
}
pub fn into_inner(self) -> H {
self.state.inner
}
}
impl<'a, 'gcx, 'tcx, H: Hasher> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tcx, H> {

View File

@ -30,7 +30,7 @@ use rustc_serialize::Encodable;
pub struct Ast<'tcx> {
id_range: IdRange,
item: Lazy<InlinedItem>,
side_tables: LazySeq<(ast::NodeId, TableEntry<'tcx>)>
side_tables: LazySeq<(ast::NodeId, TableEntry<'tcx>)>,
}
#[derive(RustcEncodable, RustcDecodable)]
@ -39,7 +39,7 @@ enum TableEntry<'tcx> {
NodeType(Ty<'tcx>),
ItemSubsts(ty::ItemSubsts<'tcx>),
Adjustment(ty::adjustment::AutoAdjustment<'tcx>),
ConstQualif(ConstQualif)
ConstQualif(ConstQualif),
}
impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
@ -48,7 +48,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
match 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)
InlinedItemRef::ImplItem(_, ii) => id_visitor.visit_impl_item(ii),
}
let ii_pos = self.position();
@ -58,12 +58,12 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
let tables_count = {
let mut visitor = SideTableEncodingIdVisitor {
ecx: self,
count: 0
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)
InlinedItemRef::ImplItem(_, ii) => visitor.visit_impl_item(ii),
}
visitor.count
};
@ -71,14 +71,14 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
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)
side_tables: LazySeq::with_position_and_length(tables_pos, tables_count),
})
}
}
struct SideTableEncodingIdVisitor<'a, 'b:'a, 'tcx:'b> {
struct SideTableEncodingIdVisitor<'a, 'b: 'a, 'tcx: 'b> {
ecx: &'a mut EncodeContext<'b, 'tcx>,
count: usize
count: usize,
}
impl<'a, 'b, 'tcx, 'v> Visitor<'v> for SideTableEncodingIdVisitor<'a, 'b, 'tcx> {
@ -114,10 +114,11 @@ pub fn decode_inlined_item<'a, 'tcx>(cdata: &CrateMetadata,
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 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,
@ -129,7 +130,7 @@ pub fn decode_inlined_item<'a, 'tcx>(cdata: &CrateMetadata,
let item_node_id = match ii {
&InlinedItem::Item(_, ref i) => i.id,
&InlinedItem::TraitItem(_, ref ti) => ti.id,
&InlinedItem::ImplItem(_, ref ii) => ii.id
&InlinedItem::ImplItem(_, ref ii) => ii.id,
};
let inlined_did = tcx.map.local_def_id(item_node_id);
tcx.register_item_type(inlined_did, tcx.lookup_item_type(orig_did));

View File

@ -54,7 +54,7 @@ pub struct ImportedFileMap {
/// The end of this FileMap within the codemap of its original crate
pub original_end_pos: syntax_pos::BytePos,
/// The imported FileMap's representation within the local codemap
pub translated_filemap: Rc<syntax_pos::FileMap>
pub translated_filemap: Rc<syntax_pos::FileMap>,
}
pub struct CrateMetadata {
@ -141,8 +141,8 @@ impl CStore {
self.metas.borrow_mut().insert(cnum, data);
}
pub fn iter_crate_data<I>(&self, mut i: I) where
I: FnMut(CrateNum, &Rc<CrateMetadata>),
pub fn iter_crate_data<I>(&self, mut i: I)
where I: FnMut(CrateNum, &Rc<CrateMetadata>)
{
for (&k, v) in self.metas.borrow().iter() {
i(k, v);
@ -150,12 +150,14 @@ impl CStore {
}
/// Like `iter_crate_data`, but passes source paths (if available) as well.
pub fn iter_crate_data_origins<I>(&self, mut i: I) where
I: FnMut(CrateNum, &CrateMetadata, Option<CrateSource>),
pub fn iter_crate_data_origins<I>(&self, mut i: I)
where I: FnMut(CrateNum, &CrateMetadata, Option<CrateSource>)
{
for (&k, v) in self.metas.borrow().iter() {
let origin = self.opt_used_crate_source(k);
origin.as_ref().map(|cs| { assert!(k == cs.cnum); });
origin.as_ref().map(|cs| {
assert!(k == cs.cnum);
});
i(k, &v, origin);
}
}
@ -167,10 +169,12 @@ impl CStore {
}
}
pub fn opt_used_crate_source(&self, cnum: CrateNum)
-> Option<CrateSource> {
self.used_crate_sources.borrow_mut()
.iter().find(|source| source.cnum == cnum).cloned()
pub fn opt_used_crate_source(&self, cnum: CrateNum) -> Option<CrateSource> {
self.used_crate_sources
.borrow_mut()
.iter()
.find(|source| source.cnum == cnum)
.cloned()
}
pub fn reset(&self) {
@ -182,19 +186,17 @@ impl CStore {
self.statically_included_foreign_items.borrow_mut().clear();
}
pub fn crate_dependencies_in_rpo(&self, krate: CrateNum) -> Vec<CrateNum>
{
pub fn crate_dependencies_in_rpo(&self, krate: CrateNum) -> Vec<CrateNum> {
let mut ordering = Vec::new();
self.push_dependencies_in_postorder(&mut ordering, krate);
ordering.reverse();
ordering
}
pub fn push_dependencies_in_postorder(&self,
ordering: &mut Vec<CrateNum>,
krate: CrateNum)
{
if ordering.contains(&krate) { return }
pub fn push_dependencies_in_postorder(&self, ordering: &mut Vec<CrateNum>, krate: CrateNum) {
if ordering.contains(&krate) {
return;
}
let data = self.get_crate_data(krate);
for &dep in data.cnum_map.borrow().iter() {
@ -215,7 +217,8 @@ impl CStore {
// In order to get this left-to-right dependency ordering, we perform a
// topological sort of all crates putting the leaves at the right-most
// positions.
pub fn do_get_used_crates(&self, prefer: LinkagePreference)
pub fn do_get_used_crates(&self,
prefer: LinkagePreference)
-> Vec<(CrateNum, Option<PathBuf>)> {
let mut ordering = Vec::new();
for (&num, _) in self.metas.borrow().iter() {
@ -223,12 +226,16 @@ impl CStore {
}
info!("topological ordering: {:?}", ordering);
ordering.reverse();
let mut libs = self.used_crate_sources.borrow()
let mut libs = self.used_crate_sources
.borrow()
.iter()
.map(|src| (src.cnum, match prefer {
LinkagePreference::RequireDynamic => src.dylib.clone().map(|p| p.0),
LinkagePreference::RequireStatic => src.rlib.clone().map(|p| p.0),
}))
.map(|src| {
(src.cnum,
match prefer {
LinkagePreference::RequireDynamic => src.dylib.clone().map(|p| p.0),
LinkagePreference::RequireStatic => src.rlib.clone().map(|p| p.0),
})
})
.collect::<Vec<_>>();
libs.sort_by(|&(a, _), &(b, _)| {
let a = ordering.iter().position(|x| *x == a);
@ -243,9 +250,7 @@ impl CStore {
self.used_libraries.borrow_mut().push((lib, kind));
}
pub fn get_used_libraries<'a>(&'a self)
-> &'a RefCell<Vec<(String,
NativeLibraryKind)>> {
pub fn get_used_libraries<'a>(&'a self) -> &'a RefCell<Vec<(String, NativeLibraryKind)>> {
&self.used_libraries
}
@ -255,13 +260,11 @@ impl CStore {
}
}
pub fn get_used_link_args<'a>(&'a self) -> &'a RefCell<Vec<String> > {
pub fn get_used_link_args<'a>(&'a self) -> &'a RefCell<Vec<String>> {
&self.used_link_args
}
pub fn add_extern_mod_stmt_cnum(&self,
emod_id: ast::NodeId,
cnum: CrateNum) {
pub fn add_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId, cnum: CrateNum) {
self.extern_mod_crate_map.borrow_mut().insert(emod_id, cnum);
}
@ -273,8 +276,7 @@ impl CStore {
self.statically_included_foreign_items.borrow().contains(&id)
}
pub fn do_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option<CrateNum>
{
pub fn do_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option<CrateNum> {
self.extern_mod_crate_map.borrow().get(&emod_id).cloned()
}
@ -288,14 +290,20 @@ impl CStore {
}
impl CrateMetadata {
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 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| {
attr.name() == "stable" || attr.name() == "unstable"
})
self.get_item_attrs(CRATE_DEF_INDEX)
.iter()
.any(|attr| attr.name() == "stable" || attr.name() == "unstable")
}
pub fn is_allocator(&self) -> bool {

View File

@ -56,19 +56,23 @@ pub struct DecodeContext<'a, 'tcx: 'a> {
// Cache the last used filemap for translating spans as an optimization.
last_filemap_index: usize,
lazy_state: LazyState
lazy_state: LazyState,
}
/// 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<TyCtxt<'a, 'tcx, 'tcx>> { None }
fn cdata(self) -> Option<&'a CrateMetadata> {
None
}
fn tcx(self) -> Option<TyCtxt<'a, 'tcx, 'tcx>> {
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)
max: NodeId::from_u32(u32::MAX),
};
DecodeContext {
opaque: opaque::Decoder::new(self.raw_bytes(), pos),
@ -77,7 +81,7 @@ pub trait Metadata<'a, 'tcx>: Copy {
from_id_range: id_range,
to_id_range: id_range,
last_filemap_index: 0,
lazy_state: LazyState::NoNode
lazy_state: LazyState::NoNode,
}
}
}
@ -92,21 +96,37 @@ impl<'a, 'tcx> Metadata<'a, 'tcx> for &'a MetadataBlob {
}
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) }
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<TyCtxt<'a, 'tcx, 'tcx>> { Some(self.1) }
fn raw_bytes(self) -> &'a [u8] {
self.0.raw_bytes()
}
fn cdata(self) -> Option<&'a CrateMetadata> {
Some(self.0)
}
fn tcx(self) -> Option<TyCtxt<'a, 'tcx, 'tcx>> {
Some(self.1)
}
}
// 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<TyCtxt<'a, 'tcx, 'tcx>> { Some(self.1) }
fn raw_bytes(self) -> &'a [u8] {
self.0.raw_bytes()
}
fn cdata(self) -> Option<&'a CrateMetadata> {
Some(self.0)
}
fn tcx(self) -> Option<TyCtxt<'a, 'tcx, 'tcx>> {
Some(self.1)
}
fn decoder(self, pos: usize) -> DecodeContext<'a, 'tcx> {
let mut dcx = (self.0, self.1).decoder(pos);
@ -125,12 +145,10 @@ impl<'a, 'tcx: 'a, T: Decodable> Lazy<T> {
}
impl<'a, 'tcx: 'a, T: Decodable> LazySeq<T> {
pub fn decode<M: Metadata<'a, 'tcx>>(self, meta: M) -> impl Iterator<Item=T> + 'a {
pub fn decode<M: Metadata<'a, 'tcx>>(self, meta: M) -> impl Iterator<Item = T> + '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()
})
(0..self.len).map(move |_| T::decode(&mut dcx).unwrap())
}
}
@ -153,20 +171,15 @@ impl<'a, 'tcx> DecodeContext<'a, 'tcx> {
r
}
fn read_lazy_distance(&mut self, min_size: usize)
-> Result<usize, <Self as Decoder>::Error> {
fn read_lazy_distance(&mut self, min_size: usize) -> Result<usize, <Self as Decoder>::Error> {
let distance = self.read_usize()?;
let position = match self.lazy_state {
LazyState::NoNode => {
bug!("read_lazy_distance: outside of a metadata node")
}
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
}
LazyState::Previous(last_min_end) => last_min_end + distance,
};
self.lazy_state = LazyState::Previous(position + min_size);
Ok(position)
@ -239,13 +252,15 @@ impl<'a, 'tcx> SpecializedDecoder<NodeId> for DecodeContext<'a, 'tcx> {
// 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);
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())))
.wrapping_add(self.to_id_range.min.as_u32())))
}
}
@ -290,10 +305,9 @@ impl<'a, 'tcx> SpecializedDecoder<Span> for DecodeContext<'a, 'tcx> {
// 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 {
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;
@ -313,10 +327,8 @@ impl<'a, 'tcx> SpecializedDecoder<Span> for DecodeContext<'a, 'tcx> {
}
};
let lo = (lo - filemap.original_start_pos) +
filemap.translated_filemap.start_pos;
let hi = (hi - filemap.original_start_pos) +
filemap.translated_filemap.start_pos;
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))
}
@ -336,7 +348,7 @@ impl<'a, 'tcx> SpecializedDecoder<Ty<'tcx>> for DecodeContext<'a, 'tcx> {
assert!(pos >= SHORTHAND_OFFSET);
let key = ty::CReaderCacheKey {
cnum: self.cdata().cnum,
pos: pos - SHORTHAND_OFFSET
pos: pos - SHORTHAND_OFFSET,
};
if let Some(ty) = tcx.rcache.borrow().get(&key).cloned() {
return Ok(ty);
@ -357,17 +369,18 @@ impl<'a, 'tcx> SpecializedDecoder<ty::GenericPredicates<'tcx>> for DecodeContext
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;
// 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;
self.with_position(pos, ty::Predicate::decode)
} else {
ty::Predicate::decode(self)
}
}).collect::<Result<Vec<_>, _>>()?
self.with_position(pos, ty::Predicate::decode)
} else {
ty::Predicate::decode(self)
}
})
.collect::<Result<Vec<_>, _>>()?,
})
}
}
@ -411,8 +424,7 @@ impl<'a, 'tcx> MetadataBlob {
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) |
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)
@ -421,9 +433,9 @@ impl<'a, 'tcx> MetadataBlob {
/// 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<Index>) -> FnvHashMap<DefKey, DefIndex> {
index.iter_enumerated(self.raw_bytes()).map(|(index, item)| {
(item.decode(self).def_key.decode(self), index)
}).collect()
index.iter_enumerated(self.raw_bytes())
.map(|(index, item)| (item.decode(self).def_key.decode(self), index))
.collect()
}
pub fn list_crate_metadata(&self, out: &mut io::Write) -> io::Result<()> {
@ -440,7 +452,7 @@ impl<'a, 'tcx> MetadataBlob {
impl<'tcx> EntryKind<'tcx> {
fn to_def(&self, did: DefId) -> Option<Def> {
Some(match *self {
EntryKind::Const => Def::Const(did),
EntryKind::Const => Def::Const(did),
EntryKind::AssociatedConst(_) => Def::AssociatedConst(did),
EntryKind::ImmStatic |
EntryKind::ForeignImmStatic => Def::Static(did, false),
@ -462,9 +474,7 @@ impl<'tcx> EntryKind<'tcx> {
EntryKind::Impl(_) |
EntryKind::DefaultImpl(_) |
EntryKind::Field |
EntryKind::Closure (_) => {
return None
}
EntryKind::Closure(_) => return None,
})
}
}
@ -476,23 +486,29 @@ impl<'a, 'tcx> CrateMetadata {
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.decode(self)
None => {
bug!("entry: id not found: {:?} in crate {:?} with number {}",
item_id,
self.name,
self.cnum)
}
Some(d) => d.decode(self),
}
}
fn local_def_id(&self, index: DefIndex) -> DefId {
DefId {
krate: self.cnum,
index: index
index: index,
}
}
fn item_name(&self, item: &Entry<'tcx>) -> ast::Name {
item.def_key.decode(self).disambiguated_data.data.get_opt_name()
item.def_key
.decode(self)
.disambiguated_data
.data
.get_opt_name()
.expect("no name in item_name")
}
@ -502,55 +518,66 @@ impl<'a, 'tcx> CrateMetadata {
pub fn get_trait_def(&self,
item_id: DefIndex,
tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ty::TraitDef<'tcx> {
tcx: TyCtxt<'a, 'tcx, 'tcx>)
-> ty::TraitDef<'tcx> {
let data = match self.entry(item_id).kind {
EntryKind::Trait(data) => data.decode(self),
_ => bug!()
_ => bug!(),
};
ty::TraitDef::new(data.unsafety, data.paren_sugar,
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: &Entry<'tcx>, index: DefIndex)
fn get_variant(&self,
item: &Entry<'tcx>,
index: DefIndex)
-> (ty::VariantDefData<'tcx, 'tcx>, Option<DefIndex>) {
let data = match item.kind {
EntryKind::Variant(data) |
EntryKind::Struct(data) |
EntryKind::Union(data) => data.decode(self),
_ => bug!()
_ => bug!(),
};
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),
f.visibility)
}).collect();
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), f.visibility)
})
.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),
ctor_kind: data.ctor_kind,
}, data.struct_ctor)
did: self.local_def_id(data.struct_ctor.unwrap_or(index)),
name: self.item_name(item),
fields: fields,
disr_val: ConstInt::Infer(data.disr),
ctor_kind: data.ctor_kind,
},
data.struct_ctor)
}
pub fn get_adt_def(&self, item_id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>)
pub fn get_adt_def(&self,
item_id: DefIndex,
tcx: TyCtxt<'a, 'tcx, 'tcx>)
-> ty::AdtDefMaster<'tcx> {
let item = self.entry(item_id);
let did = self.local_def_id(item_id);
let mut ctor_index = None;
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{
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(&item, item_id);
ctor_index = struct_ctor;
vec![variant]
@ -559,7 +586,7 @@ impl<'a, 'tcx> CrateMetadata {
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)
_ => bug!("get_adt_def called on a non-ADT {:?}", did),
};
let adt = tcx.intern_adt_def(did, kind, variants);
@ -572,33 +599,41 @@ impl<'a, 'tcx> CrateMetadata {
// to support recursive structures
for variant in &adt.variants {
for field in &variant.fields {
debug!("evaluating the type of {:?}::{:?}", variant.name, field.name);
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);
variant.name,
field.name,
ty);
}
}
adt
}
pub fn get_predicates(&self, item_id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>)
pub fn get_predicates(&self,
item_id: DefIndex,
tcx: TyCtxt<'a, 'tcx, 'tcx>)
-> ty::GenericPredicates<'tcx> {
self.entry(item_id).predicates.unwrap().decode((self, tcx))
}
pub fn get_super_predicates(&self, item_id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>)
pub fn get_super_predicates(&self,
item_id: DefIndex,
tcx: TyCtxt<'a, 'tcx, 'tcx>)
-> ty::GenericPredicates<'tcx> {
match self.entry(item_id).kind {
EntryKind::Trait(data) => {
data.decode(self).super_predicates.decode((self, tcx))
}
_ => bug!()
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>)
pub fn get_generics(&self,
item_id: DefIndex,
tcx: TyCtxt<'a, 'tcx, 'tcx>)
-> ty::Generics<'tcx> {
self.entry(item_id).generics.unwrap().decode((self, tcx))
}
@ -622,7 +657,7 @@ impl<'a, 'tcx> CrateMetadata {
fn get_impl_data(&self, id: DefIndex) -> ImplData<'tcx> {
match self.entry(id).kind {
EntryKind::Impl(data) => data.decode(self),
_ => bug!()
_ => bug!(),
}
}
@ -634,7 +669,8 @@ impl<'a, 'tcx> CrateMetadata {
self.get_impl_data(id).polarity
}
pub fn get_custom_coerce_unsized_kind(&self, id: DefIndex)
pub fn get_custom_coerce_unsized_kind(&self,
id: DefIndex)
-> Option<ty::adjustment::CustomCoerceUnsized> {
self.get_impl_data(id).coerce_unsized_kind
}
@ -674,21 +710,25 @@ impl<'a, 'tcx> CrateMetadata {
if let Some(def) = self.get_def(child_index) {
callback(def::Export {
def: def,
name: self.item_name(&self.entry(child_index))
name: self.item_name(&self.entry(child_index)),
});
}
}
continue;
}
EntryKind::Impl(_) | EntryKind::DefaultImpl(_) => continue,
EntryKind::Impl(_) |
EntryKind::DefaultImpl(_) => continue,
_ => {}
}
let def_key = child.def_key.decode(self);
if let (Some(def), Some(name)) = (self.get_def(child_index),
def_key.disambiguated_data.data.get_opt_name()) {
callback(def::Export { def: def, name: name });
if let (Some(def), Some(name)) =
(self.get_def(child_index), def_key.disambiguated_data.data.get_opt_name()) {
callback(def::Export {
def: def,
name: name,
});
// For non-reexport structs and variants add their constructors to children.
// Reexport lists automatically contain constructors when necessary.
match def {
@ -696,7 +736,10 @@ impl<'a, 'tcx> CrateMetadata {
if let Some(ctor_def_id) = self.get_struct_ctor_def_id(child_index) {
let ctor_kind = self.get_ctor_kind(child_index);
let ctor_def = Def::StructCtor(ctor_def_id, ctor_kind);
callback(def::Export { def: ctor_def, name: name });
callback(def::Export {
def: ctor_def,
name: name,
});
}
}
Def::Variant(def_id) => {
@ -704,7 +747,10 @@ impl<'a, 'tcx> CrateMetadata {
// value namespace, they are reserved for possible future use.
let ctor_kind = self.get_ctor_kind(child_index);
let ctor_def = Def::VariantCtor(def_id, ctor_kind);
callback(def::Export { def: ctor_def, name: name });
callback(def::Export {
def: ctor_def,
name: name,
});
}
_ => {}
}
@ -719,7 +765,9 @@ impl<'a, 'tcx> CrateMetadata {
}
}
pub fn maybe_get_item_ast(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefIndex)
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);
@ -737,12 +785,16 @@ impl<'a, 'tcx> CrateMetadata {
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)
pub fn maybe_get_item_mir(&self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
id: DefIndex)
-> Option<Mir<'tcx>> {
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>)
pub fn get_impl_or_trait_item(&self,
id: DefIndex,
tcx: TyCtxt<'a, 'tcx, 'tcx>)
-> Option<ty::ImplOrTraitItem<'tcx>> {
let item = self.entry(id);
let parent_and_name = || {
@ -769,9 +821,11 @@ impl<'a, 'tcx> CrateMetadata {
let ity = item.ty.unwrap().decode((self, tcx));
let fty = match ity.sty {
ty::TyFnDef(.., fty) => fty,
_ => bug!(
"the type {:?} of the method {:?} is not a function?",
ity, name)
_ => {
bug!("the type {:?} of the method {:?} is not a function?",
ity,
name)
}
};
let data = data.decode(self);
@ -799,7 +853,7 @@ impl<'a, 'tcx> CrateMetadata {
container: container.with_def_id(parent),
}))
}
_ => return None
_ => return None,
})
}
@ -821,7 +875,7 @@ impl<'a, 'tcx> CrateMetadata {
EntryKind::Struct(data) => {
data.decode(self).struct_ctor.map(|index| self.local_def_id(index))
}
_ => None
_ => None,
}
}
@ -838,17 +892,22 @@ impl<'a, 'tcx> CrateMetadata {
}
pub fn get_struct_field_names(&self, id: DefIndex) -> Vec<ast::Name> {
self.entry(id).children.decode(self).map(|index| {
self.item_name(&self.entry(index))
}).collect()
self.entry(id)
.children
.decode(self)
.map(|index| self.item_name(&self.entry(index)))
.collect()
}
fn get_attributes(&self, item: &Entry<'tcx>) -> Vec<ast::Attribute> {
item.attributes.decode(self).map(|mut attr| {
// Need new unique IDs: old thread-local IDs won't map to new threads.
attr.node.id = attr::mk_attr_id();
attr
}).collect()
item.attributes
.decode(self)
.map(|mut attr| {
// Need new unique IDs: old thread-local IDs won't map to new threads.
attr.node.id = attr::mk_attr_id();
attr
})
.collect()
}
// Translate a DefId from the current compilation environment to a DefId
@ -856,7 +915,10 @@ impl<'a, 'tcx> CrateMetadata {
fn reverse_translate_def_id(&self, did: DefId) -> Option<DefId> {
for (local, &global) in self.cnum_map.borrow().iter_enumerated() {
if global == did.krate {
return Some(DefId { krate: local, index: did.index });
return Some(DefId {
krate: local,
index: did.index,
});
}
}
@ -864,9 +926,11 @@ impl<'a, 'tcx> CrateMetadata {
}
pub fn get_inherent_implementations_for_type(&self, id: DefIndex) -> Vec<DefId> {
self.entry(id).inherent_impls.decode(self).map(|index| {
self.local_def_id(index)
}).collect()
self.entry(id)
.inherent_impls
.decode(self)
.map(|index| self.local_def_id(index))
.collect()
}
pub fn get_implementations_for_trait(&self, filter: Option<DefId>, result: &mut Vec<DefId>) {
@ -875,7 +939,7 @@ impl<'a, 'tcx> CrateMetadata {
let filter = match filter.map(|def_id| self.reverse_translate_def_id(def_id)) {
Some(Some(def_id)) => Some((def_id.krate.as_u32(), def_id.index)),
Some(None) => return,
None => None
None => None,
};
// FIXME(eddyb) Make this O(1) instead of O(n).
@ -884,9 +948,7 @@ impl<'a, 'tcx> CrateMetadata {
continue;
}
result.extend(trait_impls.impls.decode(self).map(|index| {
self.local_def_id(index)
}));
result.extend(trait_impls.impls.decode(self).map(|index| self.local_def_id(index)));
if filter.is_some() {
break;
@ -898,7 +960,7 @@ impl<'a, 'tcx> CrateMetadata {
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
_ => None,
}
})
}
@ -909,10 +971,15 @@ impl<'a, 'tcx> CrateMetadata {
}
pub fn get_dylib_dependency_formats(&self) -> Vec<(CrateNum, LinkagePreference)> {
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()
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<lang_items::LangItem> {
@ -924,7 +991,7 @@ impl<'a, 'tcx> CrateMetadata {
EntryKind::Fn(data) |
EntryKind::ForeignFn(data) => data.decode(self).arg_names,
EntryKind::Method(data) => data.decode(self).fn_data.arg_names,
_ => LazySeq::empty()
_ => LazySeq::empty(),
};
arg_names.decode(self).collect()
}
@ -937,7 +1004,7 @@ impl<'a, 'tcx> CrateMetadata {
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
_ => hir::Constness::NotConst,
};
constness == hir::Constness::Const
}
@ -953,16 +1020,14 @@ impl<'a, 'tcx> CrateMetadata {
EntryKind::ForeignImmStatic |
EntryKind::ForeignMutStatic => true,
EntryKind::Fn(_) | EntryKind::ForeignFn(_) => {
self.get_generics(id, tcx).types.is_empty()
}
EntryKind::Fn(_) |
EntryKind::ForeignFn(_) => self.get_generics(id, tcx).types.is_empty(),
_ => false,
};
if applicable {
attr::contains_extern_indicator(tcx.sess.diagnostic(),
&self.get_attributes(&item))
attr::contains_extern_indicator(tcx.sess.diagnostic(), &self.get_attributes(&item))
} else {
false
}
@ -973,36 +1038,38 @@ impl<'a, 'tcx> CrateMetadata {
EntryKind::ForeignImmStatic |
EntryKind::ForeignMutStatic |
EntryKind::ForeignFn(_) => true,
_ => false
_ => false,
}
}
pub fn is_defaulted_trait(&self, trait_id: DefIndex) -> bool {
match self.entry(trait_id).kind {
EntryKind::Trait(data) => data.decode(self).has_default_impl,
_ => bug!()
_ => bug!(),
}
}
pub fn is_default_impl(&self, impl_id: DefIndex) -> bool {
match self.entry(impl_id).kind {
match self.entry(impl_id).kind {
EntryKind::DefaultImpl(_) => true,
_ => false
_ => false,
}
}
pub fn closure_kind(&self, closure_id: DefIndex) -> ty::ClosureKind {
match self.entry(closure_id).kind {
EntryKind::Closure(data) => data.decode(self).kind,
_ => bug!()
_ => bug!(),
}
}
pub fn closure_ty(&self, closure_id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>)
pub fn closure_ty(&self,
closure_id: DefIndex,
tcx: TyCtxt<'a, 'tcx, 'tcx>)
-> ty::ClosureTy<'tcx> {
match self.entry(closure_id).kind {
EntryKind::Closure(data) => data.decode(self).ty.decode((self, tcx)),
_ => bug!()
_ => bug!(),
}
}
@ -1045,7 +1112,8 @@ impl<'a, 'tcx> CrateMetadata {
/// 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)
pub fn imported_filemaps(&'a self,
local_codemap: &codemap::CodeMap)
-> Ref<'a, Vec<cstore::ImportedFileMap>> {
{
let filemaps = self.codemap_import_info.borrow();
@ -1057,67 +1125,66 @@ impl<'a, 'tcx> CrateMetadata {
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())
};
// 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
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,
}
}
}
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();
})
.collect();
// This shouldn't borrow twice, but there is no way to downgrade RefMut to Ref.
*self.codemap_import_info.borrow_mut() = imported_filemaps;
@ -1151,8 +1218,7 @@ fn are_equal_modulo_startpos(fm1: &syntax_pos::FileMap, fm2: &syntax_pos::FileMa
}
for (mb1, mb2) in multibytes1.iter().zip(multibytes2.iter()) {
if (mb1.bytes != mb2.bytes) ||
((mb1.pos - fm1.start_pos) != (mb2.pos - fm2.start_pos)) {
if (mb1.bytes != mb2.bytes) || ((mb1.pos - fm1.start_pos) != (mb2.pos - fm2.start_pos)) {
return false;
}
}

View File

@ -799,9 +799,7 @@ pub fn C_cstr(cx: &CrateContext, s: InternedString, null_terminated: bool) -> Va
s.as_ptr() as *const c_char,
s.len() as c_uint,
!null_terminated as Bool);
let gsym = token::gensym("str");
let sym = format!("str{}", gsym.0);
let sym = cx.generate_local_symbol_name("str");
let g = declare::define_global(cx, &sym[..], val_ty(sc)).unwrap_or_else(||{
bug!("symbol `{}` is already defined", sym);
});

View File

@ -30,7 +30,6 @@ use rustc::hir;
use std::ffi::{CStr, CString};
use syntax::ast;
use syntax::attr;
use syntax::parse::token;
pub fn ptrcast(val: ValueRef, ty: Type) -> ValueRef {
unsafe {
@ -44,10 +43,7 @@ pub fn addr_of_mut(ccx: &CrateContext,
kind: &str)
-> ValueRef {
unsafe {
// FIXME: this totally needs a better name generation scheme, perhaps a simple global
// counter? Also most other uses of gensym in trans.
let gsym = token::gensym("_");
let name = format!("{}{}", kind, gsym.0);
let name = ccx.generate_local_symbol_name(kind);
let gv = declare::define_global(ccx, &name[..], val_ty(cv)).unwrap_or_else(||{
bug!("symbol `{}` is already defined", name);
});

View File

@ -166,6 +166,9 @@ pub struct LocalCrateContext<'tcx> {
type_of_depth: Cell<usize>,
symbol_map: Rc<SymbolMap<'tcx>>,
/// A counter that is used for generating local symbol names
local_gen_sym_counter: Cell<usize>,
}
// Implement DepTrackingMapConfig for `trait_cache`
@ -688,6 +691,7 @@ impl<'tcx> LocalCrateContext<'tcx> {
n_llvm_insns: Cell::new(0),
type_of_depth: Cell::new(0),
symbol_map: symbol_map,
local_gen_sym_counter: Cell::new(0),
};
let (int_type, opaque_vec_type, str_slice_ty, mut local_ccx) = {
@ -1021,6 +1025,16 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
pub fn empty_substs_for_def_id(&self, item_def_id: DefId) -> &'tcx Substs<'tcx> {
self.shared().empty_substs_for_def_id(item_def_id)
}
/// Generate a new symbol name with the given prefix. This symbol name must
/// only be used for definitions with `internal` or `private` linkage.
pub fn generate_local_symbol_name(&self, prefix: &str) -> String {
let idx = self.local().local_gen_sym_counter.get();
self.local().local_gen_sym_counter.set(idx + 1);
// Include a '.' character, so there can be no accidental conflicts with
// user defined names
format!("{}.{}", prefix, idx)
}
}
pub struct TypeOfDepthLock<'a, 'tcx: 'a>(&'a LocalCrateContext<'tcx>);

View File

@ -16,7 +16,7 @@ use self::EnumDiscriminantInfo::*;
use super::utils::{debug_context, DIB, span_start, bytes_to_bits, size_and_align_of,
get_namespace_and_span_for_item, create_DIArray, is_node_local_to_unit};
use super::namespace::mangled_name_of_item;
use super::type_names::{compute_debuginfo_type_name, push_debuginfo_type_name};
use super::type_names::compute_debuginfo_type_name;
use super::{CrateDebugContext};
use context::SharedCrateContext;
use session::Session;
@ -26,8 +26,11 @@ use llvm::debuginfo::{DIType, DIFile, DIScope, DIDescriptor, DICompositeType, DI
use rustc::hir::def::CtorKind;
use rustc::hir::def_id::DefId;
use rustc::ty::fold::TypeVisitor;
use rustc::ty::subst::Substs;
use rustc::ty::util::TypeIdHasher;
use rustc::hir;
use rustc_data_structures::blake2b;
use {type_of, machine, monomorphize};
use common::CrateContext;
use type_::Type;
@ -38,6 +41,7 @@ use util::common::path2cstr;
use libc::{c_uint, c_longlong};
use std::ffi::CString;
use std::fmt::Write;
use std::path::Path;
use std::ptr;
use std::rc::Rc;
@ -46,6 +50,7 @@ use syntax::ast;
use syntax::parse::token;
use syntax_pos::{self, Span};
// From DWARF 5.
// See http://www.dwarfstd.org/ShowIssue.php?issue=140129.1
const DW_LANG_RUST: c_uint = 0x1c;
@ -138,219 +143,58 @@ impl<'tcx> TypeMap<'tcx> {
// ID will be generated and stored for later lookup.
fn get_unique_type_id_of_type<'a>(&mut self, cx: &CrateContext<'a, 'tcx>,
type_: Ty<'tcx>) -> UniqueTypeId {
// basic type -> {:name of the type:}
// tuple -> {tuple_(:param-uid:)*}
// struct -> {struct_:svh: / :node-id:_<(:param-uid:),*> }
// enum -> {enum_:svh: / :node-id:_<(:param-uid:),*> }
// enum variant -> {variant_:variant-name:_:enum-uid:}
// reference (&) -> {& :pointee-uid:}
// mut reference (&mut) -> {&mut :pointee-uid:}
// ptr (*) -> {* :pointee-uid:}
// mut ptr (*mut) -> {*mut :pointee-uid:}
// unique ptr (box) -> {box :pointee-uid:}
// @-ptr (@) -> {@ :pointee-uid:}
// sized vec ([T; x]) -> {[:size:] :element-uid:}
// unsized vec ([T]) -> {[] :element-uid:}
// trait (T) -> {trait_:svh: / :node-id:_<(:param-uid:),*> }
// closure -> {<unsafe_> <once_> :store-sigil: |(:param-uid:),* <,_...>| -> \
// :return-type-uid: : (:bounds:)*}
// function -> {<unsafe_> <abi_> fn( (:param-uid:)* <,_...> ) -> \
// :return-type-uid:}
// Let's see if we already have something in the cache
match self.type_to_unique_id.get(&type_).cloned() {
Some(unique_type_id) => return unique_type_id,
None => { /* generate one */}
};
let mut unique_type_id = String::with_capacity(256);
unique_type_id.push('{');
let mut type_id_hasher = TypeIdHasher::new(cx.tcx(),
DebugInfoTypeIdHasher::new());
type_id_hasher.visit_ty(type_);
let hash = type_id_hasher.into_inner().into_hash();
match type_.sty {
ty::TyNever |
ty::TyBool |
ty::TyChar |
ty::TyStr |
ty::TyInt(_) |
ty::TyUint(_) |
ty::TyFloat(_) => {
push_debuginfo_type_name(cx, type_, false, &mut unique_type_id);
},
ty::TyAdt(def, substs) => {
unique_type_id.push_str(&(String::from(def.descr()) + " "));
from_def_id_and_substs(self, cx, def.did, substs, &mut unique_type_id);
}
ty::TyTuple(component_types) if component_types.is_empty() => {
push_debuginfo_type_name(cx, type_, false, &mut unique_type_id);
},
ty::TyTuple(component_types) => {
unique_type_id.push_str("tuple ");
for &component_type in component_types {
let component_type_id =
self.get_unique_type_id_of_type(cx, component_type);
let component_type_id =
self.get_unique_type_id_as_string(component_type_id);
unique_type_id.push_str(&component_type_id[..]);
}
},
ty::TyBox(inner_type) => {
unique_type_id.push_str("box ");
let inner_type_id = self.get_unique_type_id_of_type(cx, inner_type);
let inner_type_id = self.get_unique_type_id_as_string(inner_type_id);
unique_type_id.push_str(&inner_type_id[..]);
},
ty::TyRawPtr(ty::TypeAndMut { ty: inner_type, mutbl } ) => {
unique_type_id.push('*');
if mutbl == hir::MutMutable {
unique_type_id.push_str("mut");
}
let mut unique_type_id = String::with_capacity(TYPE_ID_HASH_LENGTH * 2);
let inner_type_id = self.get_unique_type_id_of_type(cx, inner_type);
let inner_type_id = self.get_unique_type_id_as_string(inner_type_id);
unique_type_id.push_str(&inner_type_id[..]);
},
ty::TyRef(_, ty::TypeAndMut { ty: inner_type, mutbl }) => {
unique_type_id.push('&');
if mutbl == hir::MutMutable {
unique_type_id.push_str("mut");
}
let inner_type_id = self.get_unique_type_id_of_type(cx, inner_type);
let inner_type_id = self.get_unique_type_id_as_string(inner_type_id);
unique_type_id.push_str(&inner_type_id[..]);
},
ty::TyArray(inner_type, len) => {
unique_type_id.push_str(&format!("[{}]", len));
let inner_type_id = self.get_unique_type_id_of_type(cx, inner_type);
let inner_type_id = self.get_unique_type_id_as_string(inner_type_id);
unique_type_id.push_str(&inner_type_id[..]);
},
ty::TySlice(inner_type) => {
unique_type_id.push_str("[]");
let inner_type_id = self.get_unique_type_id_of_type(cx, inner_type);
let inner_type_id = self.get_unique_type_id_as_string(inner_type_id);
unique_type_id.push_str(&inner_type_id[..]);
},
ty::TyTrait(ref trait_data) => {
unique_type_id.push_str("trait ");
let principal = cx.tcx().erase_late_bound_regions_and_normalize(
&trait_data.principal);
from_def_id_and_substs(self,
cx,
principal.def_id,
principal.substs,
&mut unique_type_id);
},
ty::TyFnDef(.., &ty::BareFnTy{ unsafety, abi, ref sig } ) |
ty::TyFnPtr(&ty::BareFnTy{ unsafety, abi, ref sig } ) => {
if unsafety == hir::Unsafety::Unsafe {
unique_type_id.push_str("unsafe ");
}
unique_type_id.push_str(abi.name());
unique_type_id.push_str(" fn(");
let sig = cx.tcx().erase_late_bound_regions_and_normalize(sig);
for &parameter_type in &sig.inputs {
let parameter_type_id =
self.get_unique_type_id_of_type(cx, parameter_type);
let parameter_type_id =
self.get_unique_type_id_as_string(parameter_type_id);
unique_type_id.push_str(&parameter_type_id[..]);
unique_type_id.push(',');
}
if sig.variadic {
unique_type_id.push_str("...");
}
unique_type_id.push_str(")->");
let return_type_id = self.get_unique_type_id_of_type(cx, sig.output);
let return_type_id = self.get_unique_type_id_as_string(return_type_id);
unique_type_id.push_str(&return_type_id[..]);
},
ty::TyClosure(_, substs) if substs.upvar_tys.is_empty() => {
push_debuginfo_type_name(cx, type_, false, &mut unique_type_id);
},
ty::TyClosure(_, substs) => {
unique_type_id.push_str("closure ");
for upvar_type in substs.upvar_tys {
let upvar_type_id =
self.get_unique_type_id_of_type(cx, upvar_type);
let upvar_type_id =
self.get_unique_type_id_as_string(upvar_type_id);
unique_type_id.push_str(&upvar_type_id[..]);
}
},
_ => {
bug!("get_unique_type_id_of_type() - unexpected type: {:?}",
type_)
}
};
unique_type_id.push('}');
// Trim to size before storing permanently
unique_type_id.shrink_to_fit();
for byte in hash.into_iter() {
write!(&mut unique_type_id, "{:x}", byte).unwrap();
}
let key = self.unique_id_interner.intern(&unique_type_id);
self.type_to_unique_id.insert(type_, UniqueTypeId(key));
return UniqueTypeId(key);
fn from_def_id_and_substs<'a, 'tcx>(type_map: &mut TypeMap<'tcx>,
cx: &CrateContext<'a, 'tcx>,
def_id: DefId,
substs: &Substs<'tcx>,
output: &mut String) {
// First, find out the 'real' def_id of the type. Items inlined from
// other crates have to be mapped back to their source.
let def_id = if let Some(node_id) = cx.tcx().map.as_local_node_id(def_id) {
if cx.tcx().map.is_inlined_node_id(node_id) {
// The given def_id identifies the inlined copy of a
// type definition, let's take the source of the copy.
cx.defid_for_inlined_node(node_id).unwrap()
} else {
def_id
// The hasher we are using to generate the UniqueTypeId. We want
// something that provides more than the 64 bits of the DefaultHasher.
const TYPE_ID_HASH_LENGTH: usize = 20;
struct DebugInfoTypeIdHasher {
state: blake2b::Blake2bCtx
}
impl ::std::hash::Hasher for DebugInfoTypeIdHasher {
fn finish(&self) -> u64 {
unimplemented!()
}
#[inline]
fn write(&mut self, bytes: &[u8]) {
blake2b::blake2b_update(&mut self.state, bytes);
}
}
impl DebugInfoTypeIdHasher {
fn new() -> DebugInfoTypeIdHasher {
DebugInfoTypeIdHasher {
state: blake2b::blake2b_new(TYPE_ID_HASH_LENGTH, &[])
}
} else {
def_id
};
}
// Get the crate name/disambiguator as first part of the identifier.
let crate_name = if def_id.is_local() {
cx.tcx().crate_name.clone()
} else {
cx.sess().cstore.original_crate_name(def_id.krate)
};
let crate_disambiguator = cx.tcx().crate_disambiguator(def_id.krate);
output.push_str(&crate_name[..]);
output.push_str("/");
output.push_str(&crate_disambiguator[..]);
output.push_str("/");
// Add the def-index as the second part
output.push_str(&format!("{:x}", def_id.index.as_usize()));
if substs.types().next().is_some() {
output.push('<');
for type_parameter in substs.types() {
let param_type_id =
type_map.get_unique_type_id_of_type(cx, type_parameter);
let param_type_id =
type_map.get_unique_type_id_as_string(param_type_id);
output.push_str(&param_type_id[..]);
output.push(',');
}
output.push('>');
fn into_hash(self) -> [u8; TYPE_ID_HASH_LENGTH] {
let mut hash = [0u8; TYPE_ID_HASH_LENGTH];
blake2b::blake2b_final(self.state, &mut hash);
hash
}
}
}
@ -1927,15 +1771,17 @@ pub fn create_global_var_metadata(cx: &CrateContext,
return;
}
let tcx = cx.tcx();
// Don't create debuginfo for globals inlined from other crates. The other
// crate should already contain debuginfo for it. More importantly, the
// global might not even exist in un-inlined form anywhere which would lead
// to a linker errors.
if cx.tcx().map.is_inlined_node_id(node_id) {
if tcx.map.is_inlined_node_id(node_id) {
return;
}
let node_def_id = cx.tcx().map.local_def_id(node_id);
let node_def_id = tcx.map.local_def_id(node_id);
let (var_scope, span) = get_namespace_and_span_for_item(cx, node_def_id);
let (file_metadata, line_number) = if span != syntax_pos::DUMMY_SP {
@ -1946,9 +1792,9 @@ pub fn create_global_var_metadata(cx: &CrateContext,
};
let is_local_to_unit = is_node_local_to_unit(cx, node_id);
let variable_type = cx.tcx().node_id_to_type(node_id);
let variable_type = tcx.erase_regions(&tcx.node_id_to_type(node_id));
let type_metadata = type_metadata(cx, variable_type, span);
let var_name = cx.tcx().item_name(node_def_id).to_string();
let var_name = tcx.item_name(node_def_id).to_string();
let linkage_name = mangled_name_of_item(cx, node_def_id, "");
let var_name = CString::new(var_name).unwrap();

View File

@ -15,7 +15,7 @@
//! standard implementations, it should be possible for two libraries to
//! communicate without significant data conversion.
//!
//! To get this out of the way: you should probably just use `Vec` or `HashMap`.
//! To get this out of the way: you should probably just use [`Vec`] or [`HashMap`].
//! These two collections cover most use cases for generic data storage and
//! processing. They are exceptionally good at doing what they do. All the other
//! collections in the standard library have specific use cases where they are
@ -25,10 +25,10 @@
//!
//! Rust's collections can be grouped into four major categories:
//!
//! * Sequences: `Vec`, `VecDeque`, `LinkedList`
//! * Maps: `HashMap`, `BTreeMap`
//! * Sets: `HashSet`, `BTreeSet`
//! * Misc: `BinaryHeap`
//! * Sequences: [`Vec`], [`VecDeque`], [`LinkedList`]
//! * Maps: [`HashMap`], [`BTreeMap`]
//! * Sets: [`HashSet`], [`BTreeSet`]
//! * Misc: [`BinaryHeap`]
//!
//! # When Should You Use Which Collection?
//!
@ -46,13 +46,13 @@
//! * You want a heap-allocated array.
//!
//! ### Use a `VecDeque` when:
//! * You want a `Vec` that supports efficient insertion at both ends of the
//! * You want a [`Vec`] that supports efficient insertion at both ends of the
//! sequence.
//! * You want a queue.
//! * You want a double-ended queue (deque).
//!
//! ### Use a `LinkedList` when:
//! * You want a `Vec` or `VecDeque` of unknown size, and can't tolerate
//! * You want a [`Vec`] or [`VecDeque`] of unknown size, and can't tolerate
//! amortization.
//! * You want to efficiently split and append lists.
//! * You are *absolutely* certain you *really*, *truly*, want a doubly linked
@ -92,38 +92,38 @@
//! Throughout the documentation, we will follow a few conventions. For all
//! operations, the collection's size is denoted by n. If another collection is
//! involved in the operation, it contains m elements. Operations which have an
//! *amortized* cost are suffixed with a `*`. Operations with an *expected*
//! *amortized* cost are suffixed with a `*`. Operations with an *expected*
//! cost are suffixed with a `~`.
//!
//! All amortized costs are for the potential need to resize when capacity is
//! exhausted. If a resize occurs it will take O(n) time. Our collections never
//! exhausted. If a resize occurs it will take O(n) time. Our collections never
//! automatically shrink, so removal operations aren't amortized. Over a
//! sufficiently large series of operations, the average cost per operation will
//! deterministically equal the given cost.
//!
//! Only HashMap has expected costs, due to the probabilistic nature of hashing.
//! It is theoretically possible, though very unlikely, for HashMap to
//! Only [`HashMap`] has expected costs, due to the probabilistic nature of hashing.
//! It is theoretically possible, though very unlikely, for [`HashMap`] to
//! experience worse performance.
//!
//! ## Sequences
//!
//! | | get(i) | insert(i) | remove(i) | append | split_off(i) |
//! |--------------|----------------|-----------------|----------------|--------|----------------|
//! | Vec | O(1) | O(n-i)* | O(n-i) | O(m)* | O(n-i) |
//! | VecDeque | O(1) | O(min(i, n-i))* | O(min(i, n-i)) | O(m)* | O(min(i, n-i)) |
//! | LinkedList | O(min(i, n-i)) | O(min(i, n-i)) | O(min(i, n-i)) | O(1) | O(min(i, n-i)) |
//! | | get(i) | insert(i) | remove(i) | append | split_off(i) |
//! |----------------|----------------|-----------------|----------------|--------|----------------|
//! | [`Vec`] | O(1) | O(n-i)* | O(n-i) | O(m)* | O(n-i) |
//! | [`VecDeque`] | O(1) | O(min(i, n-i))* | O(min(i, n-i)) | O(m)* | O(min(i, n-i)) |
//! | [`LinkedList`] | O(min(i, n-i)) | O(min(i, n-i)) | O(min(i, n-i)) | O(1) | O(min(i, n-i)) |
//!
//! Note that where ties occur, Vec is generally going to be faster than VecDeque, and VecDeque
//! is generally going to be faster than LinkedList.
//! Note that where ties occur, [`Vec`] is generally going to be faster than [`VecDeque`], and
//! [`VecDeque`] is generally going to be faster than [`LinkedList`].
//!
//! ## Maps
//!
//! For Sets, all operations have the cost of the equivalent Map operation.
//!
//! | | get | insert | remove | predecessor | append |
//! |----------|-----------|----------|----------|-------------|--------|
//! | HashMap | O(1)~ | O(1)~* | O(1)~ | N/A | N/A |
//! | BTreeMap | O(log n) | O(log n) | O(log n) | O(log n) | O(n+m) |
//! | | get | insert | remove | predecessor | append |
//! |--------------|-----------|----------|----------|-------------|--------|
//! | [`HashMap`] | O(1)~ | O(1)~* | O(1)~ | N/A | N/A |
//! | [`BTreeMap`] | O(log n) | O(log n) | O(log n) | O(log n) | O(n+m) |
//!
//! # Correct and Efficient Usage of Collections
//!
@ -136,7 +136,7 @@
//! ## Capacity Management
//!
//! Many collections provide several constructors and methods that refer to
//! "capacity". These collections are generally built on top of an array.
//! "capacity". These collections are generally built on top of an array.
//! Optimally, this array would be exactly the right size to fit only the
//! elements stored in the collection, but for the collection to do this would
//! be very inefficient. If the backing array was exactly the right size at all
@ -157,29 +157,29 @@
//! information to do this itself. Therefore, it is up to us programmers to give
//! it hints.
//!
//! Any `with_capacity` constructor will instruct the collection to allocate
//! Any `with_capacity()` constructor will instruct the collection to allocate
//! enough space for the specified number of elements. Ideally this will be for
//! exactly that many elements, but some implementation details may prevent
//! this. `Vec` and `VecDeque` can be relied on to allocate exactly the
//! requested amount, though. Use `with_capacity` when you know exactly how many
//! this. [`Vec`] and [`VecDeque`] can be relied on to allocate exactly the
//! requested amount, though. Use `with_capacity()` when you know exactly how many
//! elements will be inserted, or at least have a reasonable upper-bound on that
//! number.
//!
//! When anticipating a large influx of elements, the `reserve` family of
//! When anticipating a large influx of elements, the `reserve()` family of
//! methods can be used to hint to the collection how much room it should make
//! for the coming items. As with `with_capacity`, the precise behavior of
//! for the coming items. As with `with_capacity()`, the precise behavior of
//! these methods will be specific to the collection of interest.
//!
//! For optimal performance, collections will generally avoid shrinking
//! themselves. If you believe that a collection will not soon contain any more
//! elements, or just really need the memory, the `shrink_to_fit` method prompts
//! themselves. If you believe that a collection will not soon contain any more
//! elements, or just really need the memory, the `shrink_to_fit()` method prompts
//! the collection to shrink the backing array to the minimum size capable of
//! holding its elements.
//!
//! Finally, if ever you're interested in what the actual capacity of the
//! collection is, most collections provide a `capacity` method to query this
//! information on demand. This can be useful for debugging purposes, or for
//! use with the `reserve` methods.
//! collection is, most collections provide a `capacity()` method to query this
//! information on demand. This can be useful for debugging purposes, or for
//! use with the `reserve()` methods.
//!
//! ## Iterators
//!
@ -194,15 +194,15 @@
//!
//! All of the standard collections provide several iterators for performing
//! bulk manipulation of their contents. The three primary iterators almost
//! every collection should provide are `iter`, `iter_mut`, and `into_iter`.
//! every collection should provide are `iter()`, `iter_mut()`, and `into_iter()`.
//! Some of these are not provided on collections where it would be unsound or
//! unreasonable to provide them.
//!
//! `iter` provides an iterator of immutable references to all the contents of a
//! collection in the most "natural" order. For sequence collections like `Vec`,
//! `iter()` provides an iterator of immutable references to all the contents of a
//! collection in the most "natural" order. For sequence collections like [`Vec`],
//! this means the items will be yielded in increasing order of index starting
//! at 0. For ordered collections like `BTreeMap`, this means that the items
//! will be yielded in sorted order. For unordered collections like `HashMap`,
//! at 0. For ordered collections like [`BTreeMap`], this means that the items
//! will be yielded in sorted order. For unordered collections like [`HashMap`],
//! the items will be yielded in whatever order the internal representation made
//! most convenient. This is great for reading through all the contents of the
//! collection.
@ -214,8 +214,8 @@
//! }
//! ```
//!
//! `iter_mut` provides an iterator of *mutable* references in the same order as
//! `iter`. This is great for mutating all the contents of the collection.
//! `iter_mut()` provides an iterator of *mutable* references in the same order as
//! `iter()`. This is great for mutating all the contents of the collection.
//!
//! ```
//! let mut vec = vec![1, 2, 3, 4];
@ -224,12 +224,12 @@
//! }
//! ```
//!
//! `into_iter` transforms the actual collection into an iterator over its
//! `into_iter()` transforms the actual collection into an iterator over its
//! contents by-value. This is great when the collection itself is no longer
//! needed, and the values are needed elsewhere. Using `extend` with `into_iter`
//! needed, and the values are needed elsewhere. Using `extend()` with `into_iter()`
//! is the main way that contents of one collection are moved into another.
//! `extend` automatically calls `into_iter`, and takes any `T: IntoIterator`.
//! Calling `collect` on an iterator itself is also a great way to convert one
//! `extend()` automatically calls `into_iter()`, and takes any `T: `[`IntoIterator`].
//! Calling `collect()` on an iterator itself is also a great way to convert one
//! collection into another. Both of these methods should internally use the
//! capacity management tools discussed in the previous section to do this as
//! efficiently as possible.
@ -248,9 +248,9 @@
//! ```
//!
//! Iterators also provide a series of *adapter* methods for performing common
//! threads to sequences. Among the adapters are functional favorites like `map`,
//! `fold`, `skip`, and `take`. Of particular interest to collections is the
//! `rev` adapter, that reverses any iterator that supports this operation. Most
//! threads to sequences. Among the adapters are functional favorites like `map()`,
//! `fold()`, `skip()` and `take()`. Of particular interest to collections is the
//! `rev()` adapter, that reverses any iterator that supports this operation. Most
//! collections provide reversible iterators as the way to iterate over them in
//! reverse order.
//!
@ -263,27 +263,27 @@
//!
//! Several other collection methods also return iterators to yield a sequence
//! of results but avoid allocating an entire collection to store the result in.
//! This provides maximum flexibility as `collect` or `extend` can be called to
//! This provides maximum flexibility as `collect()` or `extend()` can be called to
//! "pipe" the sequence into any collection if desired. Otherwise, the sequence
//! can be looped over with a `for` loop. The iterator can also be discarded
//! after partial use, preventing the computation of the unused items.
//!
//! ## Entries
//!
//! The `entry` API is intended to provide an efficient mechanism for
//! The `entry()` API is intended to provide an efficient mechanism for
//! manipulating the contents of a map conditionally on the presence of a key or
//! not. The primary motivating use case for this is to provide efficient
//! accumulator maps. For instance, if one wishes to maintain a count of the
//! number of times each key has been seen, they will have to perform some
//! conditional logic on whether this is the first time the key has been seen or
//! not. Normally, this would require a `find` followed by an `insert`,
//! not. Normally, this would require a `find()` followed by an `insert()`,
//! effectively duplicating the search effort on each insertion.
//!
//! When a user calls `map.entry(&key)`, the map will search for the key and
//! then yield a variant of the `Entry` enum.
//!
//! If a `Vacant(entry)` is yielded, then the key *was not* found. In this case
//! the only valid operation is to `insert` a value into the entry. When this is
//! the only valid operation is to `insert()` a value into the entry. When this is
//! done, the vacant entry is consumed and converted into a mutable reference to
//! the value that was inserted. This allows for further manipulation of the
//! value beyond the lifetime of the search itself. This is useful if complex
@ -291,14 +291,14 @@
//! just inserted.
//!
//! If an `Occupied(entry)` is yielded, then the key *was* found. In this case,
//! the user has several options: they can `get`, `insert`, or `remove` the
//! the user has several options: they can `get()`, `insert()` or `remove()` the
//! value of the occupied entry. Additionally, they can convert the occupied
//! entry into a mutable reference to its value, providing symmetry to the
//! vacant `insert` case.
//! vacant `insert()` case.
//!
//! ### Examples
//!
//! Here are the two primary ways in which `entry` is used. First, a simple
//! Here are the two primary ways in which `entry()` is used. First, a simple
//! example where the logic performed on the values is trivial.
//!
//! #### Counting the number of times each character in a string occurs
@ -322,7 +322,7 @@
//! ```
//!
//! When the logic to be performed on the value is more complex, we may simply
//! use the `entry` API to ensure that the value is initialized, and perform the
//! use the `entry()` API to ensure that the value is initialized and perform the
//! logic afterwards.
//!
//! #### Tracking the inebriation of customers at a bar
@ -406,6 +406,16 @@
//! // ...but the key hasn't changed. b is still "baz", not "xyz".
//! assert_eq!(map.keys().next().unwrap().b, "baz");
//! ```
//!
//! [`Vec`]: ../../std/vec/struct.Vec.html
//! [`HashMap`]: ../../std/collections/struct.HashMap.html
//! [`VecDeque`]: ../../std/collections/struct.VecDeque.html
//! [`LinkedList`]: ../../std/collections/struct.LinkedList.html
//! [`BTreeMap`]: ../../std/collections/struct.BTreeMap.html
//! [`HashSet`]: ../../std/collections/struct.HashSet.html
//! [`BTreeSet`]: ../../std/collections/struct.BTreeSet.html
//! [`BinaryHeap`]: ../../std/collections/struct.BinaryHeap.html
//! [`IntoIterator`]: ../../std/iter/trait.IntoIterator.html
#![stable(feature = "rust1", since = "1.0.0")]

View File

@ -1294,14 +1294,18 @@ impl Into<OsString> for PathBuf {
/// This type supports a number of operations for inspecting a path, including
/// breaking the path into its components (separated by `/` or `\`, depending on
/// the platform), extracting the file name, determining whether the path is
/// absolute, and so on. More details about the overall approach can be found in
/// the module documentation.
/// absolute, and so on.
///
/// This is an *unsized* type, meaning that it must always be used behind a
/// pointer like `&` or [`Box`].
/// pointer like `&` or [`Box`]. For an owned version of this type,
/// see [`PathBuf`].
///
/// [`str`]: ../primitive.str.html
/// [`Box`]: ../boxed/struct.Box.html
/// [`PathBuf`]: struct.PathBuf.html
///
/// More details about the overall approach can be found in
/// the module documentation.
///
/// # Examples
///

View File

@ -19,12 +19,12 @@
// CHECK: @STATIC = {{.*}}, align 4
// This checks the constants from inline_enum_const
// CHECK: @ref{{[0-9]+}} = {{.*}}, align 2
// CHECK: @ref.{{[0-9]+}} = {{.*}}, align 2
// This checks the constants from {low,high}_align_const, they share the same
// constant, but the alignment differs, so the higher one should be used
// CHECK: [[LOW_HIGH:@ref[0-9]+]] = {{.*}}, align 4
// CHECK: [[LOW_HIGH_REF:@const[0-9]+]] = {{.*}} [[LOW_HIGH]]
// CHECK: [[LOW_HIGH:@ref.[0-9]+]] = {{.*}}, align 4
// CHECK: [[LOW_HIGH_REF:@const.[0-9]+]] = {{.*}} [[LOW_HIGH]]
#[derive(Copy, Clone)]

View File

@ -19,6 +19,6 @@ fn some_func<T: Foo>(foo: T) {
fn main() {
some_func(5i32);
//~^ ERROR the trait bound `i32: Foo` is not satisfied
//~| NOTE trait `i32: Foo` not satisfied
//~| NOTE the trait `Foo` is not implemented for `i32`
//~| NOTE required by `some_func`
}

View File

@ -32,5 +32,5 @@ fn ice<A>(a: A) {
let r = loop {};
r = r + a;
//~^ ERROR the trait bound `(): Add<A>` is not satisfied
//~| NOTE trait `(): Add<A>` not satisfied
//~| NOTE the trait `Add<A>` is not implemented for `()`
}

View File

@ -92,7 +92,7 @@ fn main()
let _ = v as *const [u8]; //~ ERROR cannot cast
let _ = fat_v as *const Foo;
//~^ ERROR the trait bound `[u8]: std::marker::Sized` is not satisfied
//~| NOTE trait `[u8]: std::marker::Sized` not satisfied
//~| NOTE the trait `std::marker::Sized` is not implemented for `[u8]`
//~| NOTE `[u8]` does not have a constant size known at compile-time
//~| NOTE required for the cast to the object type `Foo`
let _ = foo as *const str; //~ ERROR casting
@ -107,7 +107,7 @@ fn main()
let a : *const str = "hello";
let _ = a as *const Foo;
//~^ ERROR the trait bound `str: std::marker::Sized` is not satisfied
//~| NOTE trait `str: std::marker::Sized` not satisfied
//~| NOTE the trait `std::marker::Sized` is not implemented for `str`
//~| NOTE `str` does not have a constant size known at compile-time
//~| NOTE required for the cast to the object type `Foo`

View File

@ -12,25 +12,25 @@ use std::fmt::Debug;
const CONST_0: Debug+Sync = *(&0 as &(Debug+Sync));
//~^ ERROR `std::fmt::Debug + Sync + 'static: std::marker::Sized` is not satisfied
//~| NOTE `std::fmt::Debug + Sync + 'static: std::marker::Sized` not satisfied
//~| NOTE the trait `std::marker::Sized` is not implemented for `std::fmt::Debug + Sync + 'static`
//~| NOTE does not have a constant size known at compile-time
//~| NOTE constant expressions must have a statically known size
const CONST_FOO: str = *"foo";
//~^ ERROR `str: std::marker::Sized` is not satisfied
//~| NOTE `str: std::marker::Sized` not satisfied
//~| NOTE the trait `std::marker::Sized` is not implemented for `str`
//~| NOTE does not have a constant size known at compile-time
//~| NOTE constant expressions must have a statically known size
static STATIC_1: Debug+Sync = *(&1 as &(Debug+Sync));
//~^ ERROR `std::fmt::Debug + Sync + 'static: std::marker::Sized` is not satisfied
//~| NOTE `std::fmt::Debug + Sync + 'static: std::marker::Sized` not satisfied
//~| NOTE the trait `std::marker::Sized` is not implemented for `std::fmt::Debug + Sync + 'static`
//~| NOTE does not have a constant size known at compile-time
//~| NOTE constant expressions must have a statically known size
static STATIC_BAR: str = *"bar";
//~^ ERROR `str: std::marker::Sized` is not satisfied
//~| NOTE `str: std::marker::Sized` not satisfied
//~| NOTE the trait `std::marker::Sized` is not implemented for `str`
//~| NOTE does not have a constant size known at compile-time
//~| NOTE constant expressions must have a statically known size

View File

@ -26,7 +26,7 @@ fn send<T: Send>(_: T) {}
fn main() {
send(before());
//~^ ERROR the trait bound `std::rc::Rc<std::cell::Cell<i32>>: std::marker::Send` is not satisfied
//~| NOTE trait `std::rc::Rc<std::cell::Cell<i32>>: std::marker::Send` not satisfied
//~| NOTE the trait `std::marker::Send` is not implemented for `std::rc::Rc<std::cell::Cell<i32>>`
//~| NOTE `std::rc::Rc<std::cell::Cell<i32>>` cannot be sent between threads safely
//~| NOTE required because it appears within the type `[closure
//~| NOTE required because it appears within the type `impl std::ops::Fn<(i32,)>`
@ -34,7 +34,7 @@ fn main() {
send(after());
//~^ ERROR the trait bound `std::rc::Rc<std::cell::Cell<i32>>: std::marker::Send` is not satisfied
//~| NOTE trait `std::rc::Rc<std::cell::Cell<i32>>: std::marker::Send` not satisfied
//~| NOTE the trait `std::marker::Send` is not implemented for `std::rc::Rc<std::cell::Cell<i32>>`
//~| NOTE `std::rc::Rc<std::cell::Cell<i32>>` cannot be sent between threads safely
//~| NOTE required because it appears within the type `[closure
//~| NOTE required because it appears within the type `impl std::ops::Fn<(i32,)>`
@ -54,7 +54,7 @@ fn after() -> impl Fn(i32) {
fn cycle1() -> impl Clone {
send(cycle2().clone());
//~^ ERROR the trait bound `std::rc::Rc<std::string::String>: std::marker::Send` is not satisfied
//~| NOTE trait `std::rc::Rc<std::string::String>: std::marker::Send` not satisfied
//~| NOTE the trait `std::marker::Send` is not implemented for `std::rc::Rc<std::string::String>`
//~| NOTE `std::rc::Rc<std::string::String>` cannot be sent between threads safely
//~| NOTE required because it appears within the type `impl std::clone::Clone`
//~| NOTE required by `send`
@ -65,7 +65,7 @@ fn cycle1() -> impl Clone {
fn cycle2() -> impl Clone {
send(cycle1().clone());
//~^ ERROR the trait bound `std::rc::Rc<std::cell::Cell<i32>>: std::marker::Send` is not satisfied
//~| NOTE trait `std::rc::Rc<std::cell::Cell<i32>>: std::marker::Send` not satisfied
//~| NOTE the trait `std::marker::Send` is not implemented for `std::rc::Rc<std::cell::Cell<i32>>`
//~| NOTE `std::rc::Rc<std::cell::Cell<i32>>` cannot be sent between threads safely
//~| NOTE required because it appears within the type `impl std::clone::Clone`
//~| NOTE required by `send`

View File

@ -42,17 +42,17 @@ impl Index<Bar<usize>> for [i32] {
fn main() {
Index::index(&[] as &[i32], 2u32);
//~^ ERROR E0277
//~| NOTE not satisfied
//~| NOTE the trait `Index<u32>` is not implemented for `[i32]`
//~| NOTE trait message
//~| NOTE required by
Index::index(&[] as &[i32], Foo(2u32));
//~^ ERROR E0277
//~| NOTE not satisfied
//~| NOTE the trait `Index<Foo<u32>>` is not implemented for `[i32]`
//~| NOTE on impl for Foo
//~| NOTE required by
Index::index(&[] as &[i32], Bar(2u32));
//~^ ERROR E0277
//~| NOTE not satisfied
//~| NOTE the trait `Index<Bar<u32>>` is not implemented for `[i32]`
//~| NOTE on impl for Bar
//~| NOTE required by
}

View File

@ -29,8 +29,9 @@ impl Index<usize> for [i32] {
#[rustc_error]
fn main() {
Index::<u32>::index(&[1, 2, 3] as &[i32], 2u32); //~ ERROR E0277
//~| NOTE not satisfied
//~| NOTE a usize is required
//~| NOTE required by
Index::<u32>::index(&[1, 2, 3] as &[i32], 2u32);
//~^ ERROR E0277
//~| NOTE the trait `Index<u32>` is not implemented for `[i32]`
//~| NOTE a usize is required
//~| NOTE required by
}

View File

@ -35,9 +35,9 @@ pub fn main() {
//~^ ERROR
//~^^ NOTE a collection of type `std::option::Option<std::vec::Vec<u8>>` cannot be built from an iterator over elements of type `&u8`
//~^^^ NOTE required by `collect`
//~| NOTE trait `std::option::Option<std::vec::Vec<u8>>: MyFromIterator<&u8>` not satisfied
//~| NOTE the trait `MyFromIterator<&u8>` is not implemented for `std::option::Option<std::vec::Vec<u8>>`
let x: String = foobar(); //~ ERROR
//~^ NOTE test error `std::string::String` with `u8` `_` `u32`
//~^^ NOTE required by `foobar`
//~| NOTE trait `std::string::String: Foo<u8, _, u32>` not satisfied
//~| NOTE the trait `Foo<u8, _, u32>` is not implemented for `std::string::String`
}

View File

@ -17,10 +17,12 @@ use std::ops::Index;
#[rustc_error]
fn main() {
let x = &[1, 2, 3] as &[i32];
x[1i32]; //~ ERROR E0277
//~| NOTE trait `[i32]: std::ops::Index<i32>` not satisfied
//~| NOTE slice indices are of type `usize`
x[..1i32]; //~ ERROR E0277
//~| NOTE trait `[i32]: std::ops::Index<std::ops::RangeTo<i32>>` not satisfied
//~| NOTE slice indices are of type `usize`
x[1i32];
//~^ ERROR E0277
//~| NOTE the trait `std::ops::Index<i32>` is not implemented for `[i32]`
//~| NOTE slice indices are of type `usize`
x[..1i32];
//~^ ERROR E0277
//~| NOTE the trait `std::ops::Index<std::ops::RangeTo<i32>>` is not implemented for `[i32]`
//~| NOTE slice indices are of type `usize`
}

View File

@ -16,13 +16,13 @@ fn check<T: Iterator, U: ?Sized>() {
// suggest a where-clause, if needed
mem::size_of::<U>();
//~^ ERROR `U: std::marker::Sized` is not satisfied
//~| NOTE trait `U: std::marker::Sized` not satisfied
//~| NOTE the trait `std::marker::Sized` is not implemented for `U`
//~| HELP consider adding a `where U: std::marker::Sized` bound
//~| NOTE required by `std::mem::size_of`
mem::size_of::<Misc<U>>();
//~^ ERROR `U: std::marker::Sized` is not satisfied
//~| NOTE trait `U: std::marker::Sized` not satisfied
//~| NOTE the trait `std::marker::Sized` is not implemented for `U`
//~| HELP consider adding a `where U: std::marker::Sized` bound
//~| NOTE required because it appears within the type `Misc<U>`
//~| NOTE required by `std::mem::size_of`
@ -31,13 +31,13 @@ fn check<T: Iterator, U: ?Sized>() {
<u64 as From<T>>::from;
//~^ ERROR `u64: std::convert::From<T>` is not satisfied
//~| NOTE trait `u64: std::convert::From<T>` not satisfied
//~| NOTE the trait `std::convert::From<T>` is not implemented for `u64`
//~| HELP consider adding a `where u64: std::convert::From<T>` bound
//~| NOTE required by `std::convert::From::from`
<u64 as From<<T as Iterator>::Item>>::from;
//~^ ERROR `u64: std::convert::From<<T as std::iter::Iterator>::Item>` is not satisfied
//~| NOTE trait `u64: std::convert::From<<T as std::iter::Iterator>::Item>` not satisfied
//~| NOTE the trait `std::convert::From<<T as std::iter::Iterator>::Item>` is not implemented
//~| HELP consider adding a `where u64:
//~| NOTE required by `std::convert::From::from`
@ -45,20 +45,20 @@ fn check<T: Iterator, U: ?Sized>() {
<Misc<_> as From<T>>::from;
//~^ ERROR `Misc<_>: std::convert::From<T>` is not satisfied
//~| NOTE trait `Misc<_>: std::convert::From<T>` not satisfied
//~| NOTE the trait `std::convert::From<T>` is not implemented for `Misc<_>`
//~| NOTE required by `std::convert::From::from`
// ... and also not if the error is not related to the type
mem::size_of::<[T]>();
//~^ ERROR `[T]: std::marker::Sized` is not satisfied
//~| NOTE `[T]: std::marker::Sized` not satisfied
//~| NOTE the trait `std::marker::Sized` is not implemented for `[T]`
//~| NOTE `[T]` does not have a constant size
//~| NOTE required by `std::mem::size_of`
mem::size_of::<[&U]>();
//~^ ERROR `[&U]: std::marker::Sized` is not satisfied
//~| NOTE `[&U]: std::marker::Sized` not satisfied
//~| NOTE the trait `std::marker::Sized` is not implemented for `[&U]`
//~| NOTE `[&U]` does not have a constant size
//~| NOTE required by `std::mem::size_of`
}

View File

@ -1,7 +1,7 @@
-include ../tools.mk
# check that the compile generated symbols for strings, binaries,
# vtables, etc. have semisane names (e.g. `str1234`); it's relatively
# vtables, etc. have semisane names (e.g. `str.1234`); it's relatively
# easy to accidentally modify the compiler internals to make them
# become things like `str"str"(1234)`.
@ -10,6 +10,6 @@ OUT=$(TMPDIR)/lib.s
all:
$(RUSTC) lib.rs --emit=asm --crate-type=staticlib
# just check for symbol declarations with the names we're expecting.
grep 'str[0-9][0-9]*:' $(OUT)
grep 'byte_str[0-9][0-9]*:' $(OUT)
grep 'vtable[0-9][0-9]*' $(OUT)
grep 'str.[0-9][0-9]*:' $(OUT)
grep 'byte_str.[0-9][0-9]*:' $(OUT)
grep 'vtable.[0-9][0-9]*' $(OUT)