Auto merge of #40752 - frewsxcv:rollup, r=frewsxcv
Rollup of 6 pull requests - Successful merges: #39891, #40518, #40542, #40617, #40678, #40696 - Failed merges:
This commit is contained in:
commit
7c7753d370
44 changed files with 1734 additions and 954 deletions
|
@ -6,6 +6,7 @@ RUN yum upgrade -y && yum install -y \
|
||||||
curl \
|
curl \
|
||||||
bzip2 \
|
bzip2 \
|
||||||
gcc \
|
gcc \
|
||||||
|
gcc-c++ \
|
||||||
make \
|
make \
|
||||||
glibc-devel \
|
glibc-devel \
|
||||||
perl \
|
perl \
|
||||||
|
|
|
@ -13,12 +13,14 @@ set -ex
|
||||||
|
|
||||||
source shared.sh
|
source shared.sh
|
||||||
|
|
||||||
curl https://ftp.gnu.org/gnu/gcc/gcc-4.7.4/gcc-4.7.4.tar.bz2 | tar xjf -
|
GCC=4.8.5
|
||||||
cd gcc-4.7.4
|
|
||||||
|
curl https://ftp.gnu.org/gnu/gcc/gcc-$GCC/gcc-$GCC.tar.bz2 | tar xjf -
|
||||||
|
cd gcc-$GCC
|
||||||
./contrib/download_prerequisites
|
./contrib/download_prerequisites
|
||||||
mkdir ../gcc-build
|
mkdir ../gcc-build
|
||||||
cd ../gcc-build
|
cd ../gcc-build
|
||||||
hide_output ../gcc-4.7.4/configure \
|
hide_output ../gcc-$GCC/configure \
|
||||||
--prefix=/rustroot \
|
--prefix=/rustroot \
|
||||||
--enable-languages=c,c++
|
--enable-languages=c,c++
|
||||||
hide_output make -j10
|
hide_output make -j10
|
||||||
|
@ -27,5 +29,5 @@ ln -nsf gcc /rustroot/bin/cc
|
||||||
|
|
||||||
cd ..
|
cd ..
|
||||||
rm -rf gcc-build
|
rm -rf gcc-build
|
||||||
rm -rf gcc-4.7.4
|
rm -rf gcc-$GCC
|
||||||
yum erase -y gcc binutils
|
yum erase -y gcc gcc-c++ binutils
|
||||||
|
|
|
@ -78,33 +78,86 @@ impl serialize::UseSpecializedDecodable for CrateNum {
|
||||||
/// A DefIndex is an index into the hir-map for a crate, identifying a
|
/// A DefIndex is an index into the hir-map for a crate, identifying a
|
||||||
/// particular definition. It should really be considered an interned
|
/// particular definition. It should really be considered an interned
|
||||||
/// shorthand for a particular DefPath.
|
/// shorthand for a particular DefPath.
|
||||||
|
///
|
||||||
|
/// At the moment we are allocating the numerical values of DefIndexes into two
|
||||||
|
/// ranges: the "low" range (starting at zero) and the "high" range (starting at
|
||||||
|
/// DEF_INDEX_HI_START). This allows us to allocate the DefIndexes of all
|
||||||
|
/// item-likes (Items, TraitItems, and ImplItems) into one of these ranges and
|
||||||
|
/// consequently use a simple array for lookup tables keyed by DefIndex and
|
||||||
|
/// known to be densely populated. This is especially important for the HIR map.
|
||||||
|
///
|
||||||
|
/// Since the DefIndex is mostly treated as an opaque ID, you probably
|
||||||
|
/// don't have to care about these ranges.
|
||||||
#[derive(Clone, Debug, Eq, Ord, PartialOrd, PartialEq, RustcEncodable,
|
#[derive(Clone, Debug, Eq, Ord, PartialOrd, PartialEq, RustcEncodable,
|
||||||
RustcDecodable, Hash, Copy)]
|
RustcDecodable, Hash, Copy)]
|
||||||
pub struct DefIndex(u32);
|
pub struct DefIndex(u32);
|
||||||
|
|
||||||
impl DefIndex {
|
impl DefIndex {
|
||||||
|
#[inline]
|
||||||
pub fn new(x: usize) -> DefIndex {
|
pub fn new(x: usize) -> DefIndex {
|
||||||
assert!(x < (u32::MAX as usize));
|
assert!(x < (u32::MAX as usize));
|
||||||
DefIndex(x as u32)
|
DefIndex(x as u32)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn from_u32(x: u32) -> DefIndex {
|
pub fn from_u32(x: u32) -> DefIndex {
|
||||||
DefIndex(x)
|
DefIndex(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn as_usize(&self) -> usize {
|
pub fn as_usize(&self) -> usize {
|
||||||
self.0 as usize
|
self.0 as usize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn as_u32(&self) -> u32 {
|
pub fn as_u32(&self) -> u32 {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn address_space(&self) -> DefIndexAddressSpace {
|
||||||
|
if self.0 < DEF_INDEX_HI_START.0 {
|
||||||
|
DefIndexAddressSpace::Low
|
||||||
|
} else {
|
||||||
|
DefIndexAddressSpace::High
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Converts this DefIndex into a zero-based array index.
|
||||||
|
/// This index is the offset within the given "range" of the DefIndex,
|
||||||
|
/// that is, if the DefIndex is part of the "high" range, the resulting
|
||||||
|
/// index will be (DefIndex - DEF_INDEX_HI_START).
|
||||||
|
#[inline]
|
||||||
|
pub fn as_array_index(&self) -> usize {
|
||||||
|
(self.0 & !DEF_INDEX_HI_START.0) as usize
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The start of the "high" range of DefIndexes.
|
||||||
|
const DEF_INDEX_HI_START: DefIndex = DefIndex(1 << 31);
|
||||||
|
|
||||||
/// The crate root is always assigned index 0 by the AST Map code,
|
/// The crate root is always assigned index 0 by the AST Map code,
|
||||||
/// thanks to `NodeCollector::new`.
|
/// thanks to `NodeCollector::new`.
|
||||||
pub const CRATE_DEF_INDEX: DefIndex = DefIndex(0);
|
pub const CRATE_DEF_INDEX: DefIndex = DefIndex(0);
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
|
||||||
|
pub enum DefIndexAddressSpace {
|
||||||
|
Low = 0,
|
||||||
|
High = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DefIndexAddressSpace {
|
||||||
|
#[inline]
|
||||||
|
pub fn index(&self) -> usize {
|
||||||
|
*self as usize
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn start(&self) -> usize {
|
||||||
|
self.index() * DEF_INDEX_HI_START.as_usize()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A DefId identifies a particular *definition*, by combining a crate
|
/// A DefId identifies a particular *definition*, by combining a crate
|
||||||
/// index and a def index.
|
/// 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)]
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -9,13 +9,15 @@
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use hir::map::definitions::*;
|
use hir::map::definitions::*;
|
||||||
use hir::def_id::{CRATE_DEF_INDEX, DefIndex};
|
use hir::def_id::{CRATE_DEF_INDEX, DefIndex, DefIndexAddressSpace};
|
||||||
|
|
||||||
use syntax::ast::*;
|
use syntax::ast::*;
|
||||||
use syntax::ext::hygiene::Mark;
|
use syntax::ext::hygiene::Mark;
|
||||||
use syntax::visit;
|
use syntax::visit;
|
||||||
use syntax::symbol::{Symbol, keywords};
|
use syntax::symbol::{Symbol, keywords};
|
||||||
|
|
||||||
|
use hir::map::{ITEM_LIKE_SPACE, REGULAR_SPACE};
|
||||||
|
|
||||||
/// Creates def ids for nodes in the AST.
|
/// Creates def ids for nodes in the AST.
|
||||||
pub struct DefCollector<'a> {
|
pub struct DefCollector<'a> {
|
||||||
definitions: &'a mut Definitions,
|
definitions: &'a mut Definitions,
|
||||||
|
@ -39,23 +41,31 @@ impl<'a> DefCollector<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn collect_root(&mut self) {
|
pub fn collect_root(&mut self) {
|
||||||
let root = self.create_def_with_parent(None, CRATE_NODE_ID, DefPathData::CrateRoot);
|
let root = self.create_def_with_parent(None,
|
||||||
|
CRATE_NODE_ID,
|
||||||
|
DefPathData::CrateRoot,
|
||||||
|
ITEM_LIKE_SPACE);
|
||||||
assert_eq!(root, CRATE_DEF_INDEX);
|
assert_eq!(root, CRATE_DEF_INDEX);
|
||||||
self.parent_def = Some(root);
|
self.parent_def = Some(root);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_def(&mut self, node_id: NodeId, data: DefPathData) -> DefIndex {
|
fn create_def(&mut self,
|
||||||
|
node_id: NodeId,
|
||||||
|
data: DefPathData,
|
||||||
|
address_space: DefIndexAddressSpace)
|
||||||
|
-> DefIndex {
|
||||||
let parent_def = self.parent_def;
|
let parent_def = self.parent_def;
|
||||||
debug!("create_def(node_id={:?}, data={:?}, parent_def={:?})", node_id, data, parent_def);
|
debug!("create_def(node_id={:?}, data={:?}, parent_def={:?})", node_id, data, parent_def);
|
||||||
self.definitions.create_def_with_parent(parent_def, node_id, data)
|
self.definitions.create_def_with_parent(parent_def, node_id, data, address_space)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_def_with_parent(&mut self,
|
fn create_def_with_parent(&mut self,
|
||||||
parent: Option<DefIndex>,
|
parent: Option<DefIndex>,
|
||||||
node_id: NodeId,
|
node_id: NodeId,
|
||||||
data: DefPathData)
|
data: DefPathData,
|
||||||
|
address_space: DefIndexAddressSpace)
|
||||||
-> DefIndex {
|
-> DefIndex {
|
||||||
self.definitions.create_def_with_parent(parent, node_id, data)
|
self.definitions.create_def_with_parent(parent, node_id, data, address_space)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_def: DefIndex, f: F) {
|
pub fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_def: DefIndex, f: F) {
|
||||||
|
@ -76,7 +86,7 @@ impl<'a> DefCollector<'a> {
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.create_def(expr.id, DefPathData::Initializer);
|
self.create_def(expr.id, DefPathData::Initializer, REGULAR_SPACE);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_macro_invoc(&mut self, id: NodeId, const_expr: bool) {
|
fn visit_macro_invoc(&mut self, id: NodeId, const_expr: bool) {
|
||||||
|
@ -118,14 +128,16 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
|
||||||
ViewPathSimple(..) => {}
|
ViewPathSimple(..) => {}
|
||||||
ViewPathList(_, ref imports) => {
|
ViewPathList(_, ref imports) => {
|
||||||
for import in imports {
|
for import in imports {
|
||||||
self.create_def(import.node.id, DefPathData::Misc);
|
self.create_def(import.node.id,
|
||||||
|
DefPathData::Misc,
|
||||||
|
ITEM_LIKE_SPACE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DefPathData::Misc
|
DefPathData::Misc
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let def = self.create_def(i.id, def_data);
|
let def = self.create_def(i.id, def_data, ITEM_LIKE_SPACE);
|
||||||
|
|
||||||
self.with_parent(def, |this| {
|
self.with_parent(def, |this| {
|
||||||
match i.node {
|
match i.node {
|
||||||
|
@ -133,12 +145,15 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
|
||||||
for v in &enum_definition.variants {
|
for v in &enum_definition.variants {
|
||||||
let variant_def_index =
|
let variant_def_index =
|
||||||
this.create_def(v.node.data.id(),
|
this.create_def(v.node.data.id(),
|
||||||
DefPathData::EnumVariant(v.node.name.name.as_str()));
|
DefPathData::EnumVariant(v.node.name.name.as_str()),
|
||||||
|
REGULAR_SPACE);
|
||||||
this.with_parent(variant_def_index, |this| {
|
this.with_parent(variant_def_index, |this| {
|
||||||
for (index, field) in v.node.data.fields().iter().enumerate() {
|
for (index, field) in v.node.data.fields().iter().enumerate() {
|
||||||
let name = field.ident.map(|ident| ident.name)
|
let name = field.ident.map(|ident| ident.name)
|
||||||
.unwrap_or_else(|| Symbol::intern(&index.to_string()));
|
.unwrap_or_else(|| Symbol::intern(&index.to_string()));
|
||||||
this.create_def(field.id, DefPathData::Field(name.as_str()));
|
this.create_def(field.id,
|
||||||
|
DefPathData::Field(name.as_str()),
|
||||||
|
REGULAR_SPACE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(ref expr) = v.node.disr_expr {
|
if let Some(ref expr) = v.node.disr_expr {
|
||||||
|
@ -151,13 +166,14 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
|
||||||
// If this is a tuple-like struct, register the constructor.
|
// If this is a tuple-like struct, register the constructor.
|
||||||
if !struct_def.is_struct() {
|
if !struct_def.is_struct() {
|
||||||
this.create_def(struct_def.id(),
|
this.create_def(struct_def.id(),
|
||||||
DefPathData::StructCtor);
|
DefPathData::StructCtor,
|
||||||
|
REGULAR_SPACE);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (index, field) in struct_def.fields().iter().enumerate() {
|
for (index, field) in struct_def.fields().iter().enumerate() {
|
||||||
let name = field.ident.map(|ident| ident.name.as_str())
|
let name = field.ident.map(|ident| ident.name.as_str())
|
||||||
.unwrap_or(Symbol::intern(&index.to_string()).as_str());
|
.unwrap_or(Symbol::intern(&index.to_string()).as_str());
|
||||||
this.create_def(field.id, DefPathData::Field(name));
|
this.create_def(field.id, DefPathData::Field(name), REGULAR_SPACE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
@ -168,7 +184,8 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
|
||||||
|
|
||||||
fn visit_foreign_item(&mut self, foreign_item: &'a ForeignItem) {
|
fn visit_foreign_item(&mut self, foreign_item: &'a ForeignItem) {
|
||||||
let def = self.create_def(foreign_item.id,
|
let def = self.create_def(foreign_item.id,
|
||||||
DefPathData::ValueNs(foreign_item.ident.name.as_str()));
|
DefPathData::ValueNs(foreign_item.ident.name.as_str()),
|
||||||
|
REGULAR_SPACE);
|
||||||
|
|
||||||
self.with_parent(def, |this| {
|
self.with_parent(def, |this| {
|
||||||
visit::walk_foreign_item(this, foreign_item);
|
visit::walk_foreign_item(this, foreign_item);
|
||||||
|
@ -177,7 +194,9 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
|
||||||
|
|
||||||
fn visit_generics(&mut self, generics: &'a Generics) {
|
fn visit_generics(&mut self, generics: &'a Generics) {
|
||||||
for ty_param in generics.ty_params.iter() {
|
for ty_param in generics.ty_params.iter() {
|
||||||
self.create_def(ty_param.id, DefPathData::TypeParam(ty_param.ident.name.as_str()));
|
self.create_def(ty_param.id,
|
||||||
|
DefPathData::TypeParam(ty_param.ident.name.as_str()),
|
||||||
|
REGULAR_SPACE);
|
||||||
}
|
}
|
||||||
|
|
||||||
visit::walk_generics(self, generics);
|
visit::walk_generics(self, generics);
|
||||||
|
@ -191,7 +210,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
|
||||||
TraitItemKind::Macro(..) => return self.visit_macro_invoc(ti.id, false),
|
TraitItemKind::Macro(..) => return self.visit_macro_invoc(ti.id, false),
|
||||||
};
|
};
|
||||||
|
|
||||||
let def = self.create_def(ti.id, def_data);
|
let def = self.create_def(ti.id, def_data, ITEM_LIKE_SPACE);
|
||||||
self.with_parent(def, |this| {
|
self.with_parent(def, |this| {
|
||||||
if let TraitItemKind::Const(_, Some(ref expr)) = ti.node {
|
if let TraitItemKind::Const(_, Some(ref expr)) = ti.node {
|
||||||
this.visit_const_expr(expr);
|
this.visit_const_expr(expr);
|
||||||
|
@ -209,7 +228,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
|
||||||
ImplItemKind::Macro(..) => return self.visit_macro_invoc(ii.id, false),
|
ImplItemKind::Macro(..) => return self.visit_macro_invoc(ii.id, false),
|
||||||
};
|
};
|
||||||
|
|
||||||
let def = self.create_def(ii.id, def_data);
|
let def = self.create_def(ii.id, def_data, ITEM_LIKE_SPACE);
|
||||||
self.with_parent(def, |this| {
|
self.with_parent(def, |this| {
|
||||||
if let ImplItemKind::Const(_, ref expr) = ii.node {
|
if let ImplItemKind::Const(_, ref expr) = ii.node {
|
||||||
this.visit_const_expr(expr);
|
this.visit_const_expr(expr);
|
||||||
|
@ -225,7 +244,9 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
|
||||||
match pat.node {
|
match pat.node {
|
||||||
PatKind::Mac(..) => return self.visit_macro_invoc(pat.id, false),
|
PatKind::Mac(..) => return self.visit_macro_invoc(pat.id, false),
|
||||||
PatKind::Ident(_, id, _) => {
|
PatKind::Ident(_, id, _) => {
|
||||||
let def = self.create_def(pat.id, DefPathData::Binding(id.node.name.as_str()));
|
let def = self.create_def(pat.id,
|
||||||
|
DefPathData::Binding(id.node.name.as_str()),
|
||||||
|
REGULAR_SPACE);
|
||||||
self.parent_def = Some(def);
|
self.parent_def = Some(def);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
@ -242,7 +263,9 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
|
||||||
ExprKind::Mac(..) => return self.visit_macro_invoc(expr.id, false),
|
ExprKind::Mac(..) => return self.visit_macro_invoc(expr.id, false),
|
||||||
ExprKind::Repeat(_, ref count) => self.visit_const_expr(count),
|
ExprKind::Repeat(_, ref count) => self.visit_const_expr(count),
|
||||||
ExprKind::Closure(..) => {
|
ExprKind::Closure(..) => {
|
||||||
let def = self.create_def(expr.id, DefPathData::ClosureExpr);
|
let def = self.create_def(expr.id,
|
||||||
|
DefPathData::ClosureExpr,
|
||||||
|
REGULAR_SPACE);
|
||||||
self.parent_def = Some(def);
|
self.parent_def = Some(def);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
@ -257,7 +280,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
|
||||||
TyKind::Mac(..) => return self.visit_macro_invoc(ty.id, false),
|
TyKind::Mac(..) => return self.visit_macro_invoc(ty.id, false),
|
||||||
TyKind::Array(_, ref length) => self.visit_const_expr(length),
|
TyKind::Array(_, ref length) => self.visit_const_expr(length),
|
||||||
TyKind::ImplTrait(..) => {
|
TyKind::ImplTrait(..) => {
|
||||||
self.create_def(ty.id, DefPathData::ImplTrait);
|
self.create_def(ty.id, DefPathData::ImplTrait, REGULAR_SPACE);
|
||||||
}
|
}
|
||||||
TyKind::Typeof(ref expr) => self.visit_const_expr(expr),
|
TyKind::Typeof(ref expr) => self.visit_const_expr(expr),
|
||||||
_ => {}
|
_ => {}
|
||||||
|
@ -266,7 +289,9 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_lifetime_def(&mut self, def: &'a LifetimeDef) {
|
fn visit_lifetime_def(&mut self, def: &'a LifetimeDef) {
|
||||||
self.create_def(def.lifetime.id, DefPathData::LifetimeDef(def.lifetime.name.as_str()));
|
self.create_def(def.lifetime.id,
|
||||||
|
DefPathData::LifetimeDef(def.lifetime.name.as_str()),
|
||||||
|
REGULAR_SPACE);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_stmt(&mut self, stmt: &'a Stmt) {
|
fn visit_stmt(&mut self, stmt: &'a Stmt) {
|
||||||
|
|
|
@ -14,8 +14,10 @@
|
||||||
//! There are also some rather random cases (like const initializer
|
//! There are also some rather random cases (like const initializer
|
||||||
//! expressions) that are mostly just leftovers.
|
//! expressions) that are mostly just leftovers.
|
||||||
|
|
||||||
use hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE};
|
use hir;
|
||||||
|
use hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE, DefIndexAddressSpace};
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
|
use rustc_data_structures::indexed_vec::IndexVec;
|
||||||
use rustc_data_structures::stable_hasher::StableHasher;
|
use rustc_data_structures::stable_hasher::StableHasher;
|
||||||
use serialize::{Encodable, Decodable, Encoder, Decoder};
|
use serialize::{Encodable, Decodable, Encoder, Decoder};
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
|
@ -29,24 +31,44 @@ use util::nodemap::NodeMap;
|
||||||
/// Internally the DefPathTable holds a tree of DefKeys, where each DefKey
|
/// Internally the DefPathTable holds a tree of DefKeys, where each DefKey
|
||||||
/// stores the DefIndex of its parent.
|
/// stores the DefIndex of its parent.
|
||||||
/// There is one DefPathTable for each crate.
|
/// There is one DefPathTable for each crate.
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct DefPathTable {
|
pub struct DefPathTable {
|
||||||
index_to_key: Vec<DefKey>,
|
index_to_key: [Vec<DefKey>; 2],
|
||||||
key_to_index: FxHashMap<DefKey, DefIndex>,
|
key_to_index: FxHashMap<DefKey, DefIndex>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Unfortunately we have to provide a manual impl of Clone because of the
|
||||||
|
// fixed-sized array field.
|
||||||
|
impl Clone for DefPathTable {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
DefPathTable {
|
||||||
|
index_to_key: [self.index_to_key[0].clone(),
|
||||||
|
self.index_to_key[1].clone()],
|
||||||
|
key_to_index: self.key_to_index.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl DefPathTable {
|
impl DefPathTable {
|
||||||
fn insert(&mut self, key: DefKey) -> DefIndex {
|
|
||||||
let index = DefIndex::new(self.index_to_key.len());
|
fn allocate(&mut self,
|
||||||
debug!("DefPathTable::insert() - {:?} <-> {:?}", key, index);
|
key: DefKey,
|
||||||
self.index_to_key.push(key.clone());
|
address_space: DefIndexAddressSpace)
|
||||||
|
-> DefIndex {
|
||||||
|
let index = {
|
||||||
|
let index_to_key = &mut self.index_to_key[address_space.index()];
|
||||||
|
let index = DefIndex::new(index_to_key.len() + address_space.start());
|
||||||
|
debug!("DefPathTable::insert() - {:?} <-> {:?}", key, index);
|
||||||
|
index_to_key.push(key.clone());
|
||||||
|
index
|
||||||
|
};
|
||||||
self.key_to_index.insert(key, index);
|
self.key_to_index.insert(key, index);
|
||||||
index
|
index
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn def_key(&self, index: DefIndex) -> DefKey {
|
pub fn def_key(&self, index: DefIndex) -> DefKey {
|
||||||
self.index_to_key[index.as_usize()].clone()
|
self.index_to_key[index.address_space().index()]
|
||||||
|
[index.as_array_index()].clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
@ -94,17 +116,28 @@ impl DefPathTable {
|
||||||
|
|
||||||
impl Encodable for DefPathTable {
|
impl Encodable for DefPathTable {
|
||||||
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
|
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
|
||||||
self.index_to_key.encode(s)
|
self.index_to_key[DefIndexAddressSpace::Low.index()].encode(s)?;
|
||||||
|
self.index_to_key[DefIndexAddressSpace::High.index()].encode(s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decodable for DefPathTable {
|
impl Decodable for DefPathTable {
|
||||||
fn decode<D: Decoder>(d: &mut D) -> Result<DefPathTable, D::Error> {
|
fn decode<D: Decoder>(d: &mut D) -> Result<DefPathTable, D::Error> {
|
||||||
let index_to_key: Vec<DefKey> = Decodable::decode(d)?;
|
let index_to_key_lo: Vec<DefKey> = Decodable::decode(d)?;
|
||||||
let key_to_index = index_to_key.iter()
|
let index_to_key_high: Vec<DefKey> = Decodable::decode(d)?;
|
||||||
.enumerate()
|
|
||||||
.map(|(index, key)| (key.clone(), DefIndex::new(index)))
|
let index_to_key = [index_to_key_lo, index_to_key_high];
|
||||||
.collect();
|
|
||||||
|
let mut key_to_index = FxHashMap();
|
||||||
|
|
||||||
|
for space in &[DefIndexAddressSpace::Low, DefIndexAddressSpace::High] {
|
||||||
|
key_to_index.extend(index_to_key[space.index()]
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(index, key)| (key.clone(),
|
||||||
|
DefIndex::new(index + space.start()))))
|
||||||
|
}
|
||||||
|
|
||||||
Ok(DefPathTable {
|
Ok(DefPathTable {
|
||||||
index_to_key: index_to_key,
|
index_to_key: index_to_key,
|
||||||
key_to_index: key_to_index,
|
key_to_index: key_to_index,
|
||||||
|
@ -116,11 +149,27 @@ impl Decodable for DefPathTable {
|
||||||
/// The definition table containing node definitions.
|
/// The definition table containing node definitions.
|
||||||
/// It holds the DefPathTable for local DefIds/DefPaths and it also stores a
|
/// It holds the DefPathTable for local DefIds/DefPaths and it also stores a
|
||||||
/// mapping from NodeIds to local DefIds.
|
/// mapping from NodeIds to local DefIds.
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct Definitions {
|
pub struct Definitions {
|
||||||
table: DefPathTable,
|
table: DefPathTable,
|
||||||
node_to_def_index: NodeMap<DefIndex>,
|
node_to_def_index: NodeMap<DefIndex>,
|
||||||
def_index_to_node: Vec<ast::NodeId>,
|
def_index_to_node: [Vec<ast::NodeId>; 2],
|
||||||
|
pub(super) node_to_hir_id: IndexVec<ast::NodeId, hir::HirId>,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unfortunately we have to provide a manual impl of Clone because of the
|
||||||
|
// fixed-sized array field.
|
||||||
|
impl Clone for Definitions {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Definitions {
|
||||||
|
table: self.table.clone(),
|
||||||
|
node_to_def_index: self.node_to_def_index.clone(),
|
||||||
|
def_index_to_node: [
|
||||||
|
self.def_index_to_node[0].clone(),
|
||||||
|
self.def_index_to_node[1].clone(),
|
||||||
|
],
|
||||||
|
node_to_hir_id: self.node_to_hir_id.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A unique identifier that we can use to lookup a definition
|
/// A unique identifier that we can use to lookup a definition
|
||||||
|
@ -206,6 +255,23 @@ impl DefPath {
|
||||||
s
|
s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a string representation of the DefPath without
|
||||||
|
/// the crate-prefix. This method is useful if you don't have
|
||||||
|
/// a TyCtxt available.
|
||||||
|
pub fn to_string_no_crate(&self) -> String {
|
||||||
|
let mut s = String::with_capacity(self.data.len() * 16);
|
||||||
|
|
||||||
|
for component in &self.data {
|
||||||
|
write!(s,
|
||||||
|
"::{}[{}]",
|
||||||
|
component.data.as_interned_str(),
|
||||||
|
component.disambiguator)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
s
|
||||||
|
}
|
||||||
|
|
||||||
pub fn deterministic_hash(&self, tcx: TyCtxt) -> u64 {
|
pub fn deterministic_hash(&self, tcx: TyCtxt) -> u64 {
|
||||||
debug!("deterministic_hash({:?})", self);
|
debug!("deterministic_hash({:?})", self);
|
||||||
let mut state = StableHasher::new();
|
let mut state = StableHasher::new();
|
||||||
|
@ -270,11 +336,12 @@ impl Definitions {
|
||||||
pub fn new() -> Definitions {
|
pub fn new() -> Definitions {
|
||||||
Definitions {
|
Definitions {
|
||||||
table: DefPathTable {
|
table: DefPathTable {
|
||||||
index_to_key: vec![],
|
index_to_key: [vec![], vec![]],
|
||||||
key_to_index: FxHashMap(),
|
key_to_index: FxHashMap(),
|
||||||
},
|
},
|
||||||
node_to_def_index: NodeMap(),
|
node_to_def_index: NodeMap(),
|
||||||
def_index_to_node: vec![],
|
def_index_to_node: [vec![], vec![]],
|
||||||
|
node_to_hir_id: IndexVec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -283,8 +350,9 @@ impl Definitions {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the number of definitions.
|
/// Get the number of definitions.
|
||||||
pub fn len(&self) -> usize {
|
pub fn def_index_counts_lo_hi(&self) -> (usize, usize) {
|
||||||
self.def_index_to_node.len()
|
(self.def_index_to_node[DefIndexAddressSpace::Low.index()].len(),
|
||||||
|
self.def_index_to_node[DefIndexAddressSpace::High.index()].len())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn def_key(&self, index: DefIndex) -> DefKey {
|
pub fn def_key(&self, index: DefIndex) -> DefKey {
|
||||||
|
@ -318,8 +386,9 @@ impl Definitions {
|
||||||
|
|
||||||
pub fn as_local_node_id(&self, def_id: DefId) -> Option<ast::NodeId> {
|
pub fn as_local_node_id(&self, def_id: DefId) -> Option<ast::NodeId> {
|
||||||
if def_id.krate == LOCAL_CRATE {
|
if def_id.krate == LOCAL_CRATE {
|
||||||
assert!(def_id.index.as_usize() < self.def_index_to_node.len());
|
let space_index = def_id.index.address_space().index();
|
||||||
Some(self.def_index_to_node[def_id.index.as_usize()])
|
let array_index = def_id.index.as_array_index();
|
||||||
|
Some(self.def_index_to_node[space_index][array_index])
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -329,7 +398,9 @@ impl Definitions {
|
||||||
pub fn create_def_with_parent(&mut self,
|
pub fn create_def_with_parent(&mut self,
|
||||||
parent: Option<DefIndex>,
|
parent: Option<DefIndex>,
|
||||||
node_id: ast::NodeId,
|
node_id: ast::NodeId,
|
||||||
data: DefPathData)
|
data: DefPathData,
|
||||||
|
// is_owner: bool)
|
||||||
|
address_space: DefIndexAddressSpace)
|
||||||
-> DefIndex {
|
-> DefIndex {
|
||||||
debug!("create_def_with_parent(parent={:?}, node_id={:?}, data={:?})",
|
debug!("create_def_with_parent(parent={:?}, node_id={:?}, data={:?})",
|
||||||
parent, node_id, data);
|
parent, node_id, data);
|
||||||
|
@ -359,14 +430,25 @@ impl Definitions {
|
||||||
debug!("create_def_with_parent: after disambiguation, key = {:?}", key);
|
debug!("create_def_with_parent: after disambiguation, key = {:?}", key);
|
||||||
|
|
||||||
// Create the definition.
|
// Create the definition.
|
||||||
let index = self.table.insert(key);
|
let index = self.table.allocate(key, address_space);
|
||||||
|
assert_eq!(index.as_array_index(),
|
||||||
|
self.def_index_to_node[address_space.index()].len());
|
||||||
|
self.def_index_to_node[address_space.index()].push(node_id);
|
||||||
|
|
||||||
debug!("create_def_with_parent: def_index_to_node[{:?} <-> {:?}", index, node_id);
|
debug!("create_def_with_parent: def_index_to_node[{:?} <-> {:?}", index, node_id);
|
||||||
self.node_to_def_index.insert(node_id, index);
|
self.node_to_def_index.insert(node_id, index);
|
||||||
assert_eq!(index.as_usize(), self.def_index_to_node.len());
|
|
||||||
self.def_index_to_node.push(node_id);
|
|
||||||
|
|
||||||
index
|
index
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Initialize the ast::NodeId to HirId mapping once it has been generated during
|
||||||
|
/// AST to HIR lowering.
|
||||||
|
pub fn init_node_id_to_hir_id_mapping(&mut self,
|
||||||
|
mapping: IndexVec<ast::NodeId, hir::HirId>) {
|
||||||
|
assert!(self.node_to_hir_id.is_empty(),
|
||||||
|
"Trying initialize NodeId -> HirId mapping twice");
|
||||||
|
self.node_to_hir_id = mapping;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DefPathData {
|
impl DefPathData {
|
||||||
|
|
184
src/librustc/hir/map/hir_id_validator.rs
Normal file
184
src/librustc/hir/map/hir_id_validator.rs
Normal file
|
@ -0,0 +1,184 @@
|
||||||
|
// Copyright 2017 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 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
use hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX};
|
||||||
|
use hir::{self, intravisit, HirId, ItemLocalId};
|
||||||
|
use syntax::ast::NodeId;
|
||||||
|
use hir::itemlikevisit::ItemLikeVisitor;
|
||||||
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
|
|
||||||
|
pub fn check_crate<'hir>(hir_map: &hir::map::Map<'hir>) {
|
||||||
|
let mut outer_visitor = OuterVisitor {
|
||||||
|
hir_map: hir_map,
|
||||||
|
errors: vec![],
|
||||||
|
};
|
||||||
|
|
||||||
|
hir_map.dep_graph.with_ignore(|| {
|
||||||
|
hir_map.krate().visit_all_item_likes(&mut outer_visitor);
|
||||||
|
if !outer_visitor.errors.is_empty() {
|
||||||
|
let message = outer_visitor
|
||||||
|
.errors
|
||||||
|
.iter()
|
||||||
|
.fold(String::new(), |s1, s2| s1 + "\n" + s2);
|
||||||
|
bug!("{}", message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
struct HirIdValidator<'a, 'hir: 'a> {
|
||||||
|
hir_map: &'a hir::map::Map<'hir>,
|
||||||
|
owner_def_index: Option<DefIndex>,
|
||||||
|
hir_ids_seen: FxHashMap<ItemLocalId, NodeId>,
|
||||||
|
errors: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct OuterVisitor<'a, 'hir: 'a> {
|
||||||
|
hir_map: &'a hir::map::Map<'hir>,
|
||||||
|
errors: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'hir: 'a> OuterVisitor<'a, 'hir> {
|
||||||
|
fn new_inner_visitor(&self,
|
||||||
|
hir_map: &'a hir::map::Map<'hir>)
|
||||||
|
-> HirIdValidator<'a, 'hir> {
|
||||||
|
HirIdValidator {
|
||||||
|
hir_map: hir_map,
|
||||||
|
owner_def_index: None,
|
||||||
|
hir_ids_seen: FxHashMap(),
|
||||||
|
errors: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'hir: 'a> ItemLikeVisitor<'hir> for OuterVisitor<'a, 'hir> {
|
||||||
|
fn visit_item(&mut self, i: &'hir hir::Item) {
|
||||||
|
let mut inner_visitor = self.new_inner_visitor(self.hir_map);
|
||||||
|
inner_visitor.check(i.id, |this| intravisit::walk_item(this, i));
|
||||||
|
self.errors.extend(inner_visitor.errors.drain(..));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_trait_item(&mut self, i: &'hir hir::TraitItem) {
|
||||||
|
let mut inner_visitor = self.new_inner_visitor(self.hir_map);
|
||||||
|
inner_visitor.check(i.id, |this| intravisit::walk_trait_item(this, i));
|
||||||
|
self.errors.extend(inner_visitor.errors.drain(..));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_impl_item(&mut self, i: &'hir hir::ImplItem) {
|
||||||
|
let mut inner_visitor = self.new_inner_visitor(self.hir_map);
|
||||||
|
inner_visitor.check(i.id, |this| intravisit::walk_impl_item(this, i));
|
||||||
|
self.errors.extend(inner_visitor.errors.drain(..));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'hir: 'a> HirIdValidator<'a, 'hir> {
|
||||||
|
|
||||||
|
fn check<F: FnOnce(&mut HirIdValidator<'a, 'hir>)>(&mut self,
|
||||||
|
node_id: NodeId,
|
||||||
|
walk: F) {
|
||||||
|
assert!(self.owner_def_index.is_none());
|
||||||
|
let owner_def_index = self.hir_map.local_def_id(node_id).index;
|
||||||
|
self.owner_def_index = Some(owner_def_index);
|
||||||
|
walk(self);
|
||||||
|
|
||||||
|
if owner_def_index == CRATE_DEF_INDEX {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// There's always at least one entry for the owning item itself
|
||||||
|
let max = self.hir_ids_seen
|
||||||
|
.keys()
|
||||||
|
.map(|local_id| local_id.as_usize())
|
||||||
|
.max()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
if max != self.hir_ids_seen.len() - 1 {
|
||||||
|
// Collect the missing ItemLocalIds
|
||||||
|
let missing: Vec<_> = (0 .. max + 1)
|
||||||
|
.filter(|&i| !self.hir_ids_seen.contains_key(&ItemLocalId(i as u32)))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
// Try to map those to something more useful
|
||||||
|
let mut missing_items = vec![];
|
||||||
|
|
||||||
|
for local_id in missing {
|
||||||
|
let hir_id = HirId {
|
||||||
|
owner: owner_def_index,
|
||||||
|
local_id: ItemLocalId(local_id as u32),
|
||||||
|
};
|
||||||
|
|
||||||
|
// We are already in ICE mode here, so doing a linear search
|
||||||
|
// should be fine.
|
||||||
|
let (node_id, _) = self.hir_map
|
||||||
|
.definitions()
|
||||||
|
.node_to_hir_id
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.find(|&(_, &entry)| hir_id == entry)
|
||||||
|
.unwrap();
|
||||||
|
let node_id = NodeId::new(node_id);
|
||||||
|
missing_items.push(format!("[local_id: {}, node:{}]",
|
||||||
|
local_id,
|
||||||
|
self.hir_map.node_to_string(node_id)));
|
||||||
|
}
|
||||||
|
|
||||||
|
self.errors.push(format!(
|
||||||
|
"ItemLocalIds not assigned densely in {}. \
|
||||||
|
Max ItemLocalId = {}, missing IDs = {:?}",
|
||||||
|
self.hir_map.def_path(DefId::local(owner_def_index)).to_string_no_crate(),
|
||||||
|
max,
|
||||||
|
missing_items));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'hir: 'a> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> {
|
||||||
|
|
||||||
|
fn nested_visit_map<'this>(&'this mut self)
|
||||||
|
-> intravisit::NestedVisitorMap<'this, 'hir> {
|
||||||
|
intravisit::NestedVisitorMap::OnlyBodies(self.hir_map)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_id(&mut self, node_id: NodeId) {
|
||||||
|
let owner = self.owner_def_index.unwrap();
|
||||||
|
let stable_id = self.hir_map.definitions().node_to_hir_id[node_id];
|
||||||
|
|
||||||
|
if stable_id == hir::DUMMY_HIR_ID {
|
||||||
|
self.errors.push(format!("HirIdValidator: No HirId assigned for NodeId {}: {:?}",
|
||||||
|
node_id,
|
||||||
|
self.hir_map.node_to_string(node_id)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if owner != stable_id.owner {
|
||||||
|
self.errors.push(format!(
|
||||||
|
"HirIdValidator: The recorded owner of {} is {} instead of {}",
|
||||||
|
self.hir_map.node_to_string(node_id),
|
||||||
|
self.hir_map.def_path(DefId::local(stable_id.owner)).to_string_no_crate(),
|
||||||
|
self.hir_map.def_path(DefId::local(owner)).to_string_no_crate()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(prev) = self.hir_ids_seen.insert(stable_id.local_id, node_id) {
|
||||||
|
if prev != node_id {
|
||||||
|
self.errors.push(format!(
|
||||||
|
"HirIdValidator: Same HirId {}/{} assigned for nodes {} and {}",
|
||||||
|
self.hir_map.def_path(DefId::local(stable_id.owner)).to_string_no_crate(),
|
||||||
|
stable_id.local_id.as_usize(),
|
||||||
|
self.hir_map.node_to_string(prev),
|
||||||
|
self.hir_map.node_to_string(node_id)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_impl_item_ref(&mut self, _: &'hir hir::ImplItemRef) {
|
||||||
|
// Explicitly do nothing here. ImplItemRefs contain hir::Visibility
|
||||||
|
// values that actually belong to an ImplItem instead of the ItemImpl
|
||||||
|
// we are currently in. So for those it's correct that they have a
|
||||||
|
// different owner.
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,7 +17,7 @@ pub use self::definitions::{Definitions, DefKey, DefPath, DefPathData,
|
||||||
|
|
||||||
use dep_graph::{DepGraph, DepNode};
|
use dep_graph::{DepGraph, DepNode};
|
||||||
|
|
||||||
use hir::def_id::{CRATE_DEF_INDEX, DefId, DefIndex};
|
use hir::def_id::{CRATE_DEF_INDEX, DefId, DefIndex, DefIndexAddressSpace};
|
||||||
|
|
||||||
use syntax::abi::Abi;
|
use syntax::abi::Abi;
|
||||||
use syntax::ast::{self, Name, NodeId, CRATE_NODE_ID};
|
use syntax::ast::{self, Name, NodeId, CRATE_NODE_ID};
|
||||||
|
@ -36,6 +36,10 @@ pub mod blocks;
|
||||||
mod collector;
|
mod collector;
|
||||||
mod def_collector;
|
mod def_collector;
|
||||||
pub mod definitions;
|
pub mod definitions;
|
||||||
|
mod hir_id_validator;
|
||||||
|
|
||||||
|
pub const ITEM_LIKE_SPACE: DefIndexAddressSpace = DefIndexAddressSpace::Low;
|
||||||
|
pub const REGULAR_SPACE: DefIndexAddressSpace = DefIndexAddressSpace::High;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub enum Node<'hir> {
|
pub enum Node<'hir> {
|
||||||
|
@ -346,10 +350,6 @@ impl<'hir> Map<'hir> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn num_local_def_ids(&self) -> usize {
|
|
||||||
self.definitions.len()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn definitions(&self) -> &Definitions {
|
pub fn definitions(&self) -> &Definitions {
|
||||||
&self.definitions
|
&self.definitions
|
||||||
}
|
}
|
||||||
|
@ -964,13 +964,17 @@ pub fn map_crate<'hir>(forest: &'hir mut Forest,
|
||||||
entries, vector_length, (entries as f64 / vector_length as f64) * 100.);
|
entries, vector_length, (entries as f64 / vector_length as f64) * 100.);
|
||||||
}
|
}
|
||||||
|
|
||||||
Map {
|
let map = Map {
|
||||||
forest: forest,
|
forest: forest,
|
||||||
dep_graph: forest.dep_graph.clone(),
|
dep_graph: forest.dep_graph.clone(),
|
||||||
map: map,
|
map: map,
|
||||||
definitions: definitions,
|
definitions: definitions,
|
||||||
inlined_bodies: RefCell::new(DefIdMap()),
|
inlined_bodies: RefCell::new(DefIdMap()),
|
||||||
}
|
};
|
||||||
|
|
||||||
|
hir_id_validator::check_crate(&map);
|
||||||
|
|
||||||
|
map
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Identical to the `PpAnn` implementation for `hir::Crate`,
|
/// Identical to the `PpAnn` implementation for `hir::Crate`,
|
||||||
|
|
|
@ -30,7 +30,7 @@ pub use self::Visibility::{Public, Inherited};
|
||||||
pub use self::PathParameters::*;
|
pub use self::PathParameters::*;
|
||||||
|
|
||||||
use hir::def::Def;
|
use hir::def::Def;
|
||||||
use hir::def_id::DefId;
|
use hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX};
|
||||||
use util::nodemap::{NodeMap, FxHashSet};
|
use util::nodemap::{NodeMap, FxHashSet};
|
||||||
|
|
||||||
use syntax_pos::{Span, ExpnId, DUMMY_SP};
|
use syntax_pos::{Span, ExpnId, DUMMY_SP};
|
||||||
|
@ -43,6 +43,8 @@ use syntax::symbol::{Symbol, keywords};
|
||||||
use syntax::tokenstream::TokenStream;
|
use syntax::tokenstream::TokenStream;
|
||||||
use syntax::util::ThinVec;
|
use syntax::util::ThinVec;
|
||||||
|
|
||||||
|
use rustc_data_structures::indexed_vec;
|
||||||
|
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
|
@ -73,6 +75,63 @@ pub mod pat_util;
|
||||||
pub mod print;
|
pub mod print;
|
||||||
pub mod svh;
|
pub mod svh;
|
||||||
|
|
||||||
|
/// A HirId uniquely identifies a node in the HIR of then current crate. It is
|
||||||
|
/// composed of the `owner`, which is the DefIndex of the directly enclosing
|
||||||
|
/// hir::Item, hir::TraitItem, or hir::ImplItem (i.e. the closest "item-like"),
|
||||||
|
/// and the `local_id` which is unique within the given owner.
|
||||||
|
///
|
||||||
|
/// This two-level structure makes for more stable values: One can move an item
|
||||||
|
/// around within the source code, or add or remove stuff before it, without
|
||||||
|
/// the local_id part of the HirId changing, which is a very useful property
|
||||||
|
/// incremental compilation where we have to persist things through changes to
|
||||||
|
/// the code base.
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug,
|
||||||
|
RustcEncodable, RustcDecodable)]
|
||||||
|
pub struct HirId {
|
||||||
|
pub owner: DefIndex,
|
||||||
|
pub local_id: ItemLocalId,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An `ItemLocalId` uniquely identifies something within a given "item-like",
|
||||||
|
/// that is within a hir::Item, hir::TraitItem, or hir::ImplItem. There is no
|
||||||
|
/// guarantee that the numerical value of a given `ItemLocalId` corresponds to
|
||||||
|
/// the node's position within the owning item in any way, but there is a
|
||||||
|
/// guarantee that the `LocalItemId`s within an owner occupy a dense range of
|
||||||
|
/// integers starting at zero, so a mapping that maps all or most nodes within
|
||||||
|
/// an "item-like" to something else can be implement by a `Vec` instead of a
|
||||||
|
/// tree or hash map.
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug,
|
||||||
|
RustcEncodable, RustcDecodable)]
|
||||||
|
pub struct ItemLocalId(pub u32);
|
||||||
|
|
||||||
|
impl ItemLocalId {
|
||||||
|
pub fn as_usize(&self) -> usize {
|
||||||
|
self.0 as usize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl indexed_vec::Idx for ItemLocalId {
|
||||||
|
fn new(idx: usize) -> Self {
|
||||||
|
debug_assert!((idx as u32) as usize == idx);
|
||||||
|
ItemLocalId(idx as u32)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn index(self) -> usize {
|
||||||
|
self.0 as usize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The `HirId` corresponding to CRATE_NODE_ID and CRATE_DEF_INDEX
|
||||||
|
pub const CRATE_HIR_ID: HirId = HirId {
|
||||||
|
owner: CRATE_DEF_INDEX,
|
||||||
|
local_id: ItemLocalId(0)
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const DUMMY_HIR_ID: HirId = HirId {
|
||||||
|
owner: CRATE_DEF_INDEX,
|
||||||
|
local_id: ItemLocalId(!0)
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)]
|
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)]
|
||||||
pub struct Lifetime {
|
pub struct Lifetime {
|
||||||
pub id: NodeId,
|
pub id: NodeId,
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use rustc::ty::TyCtxt;
|
use ty::TyCtxt;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use syntax::codemap::CodeMap;
|
use syntax::codemap::CodeMap;
|
||||||
use syntax_pos::{BytePos, FileMap};
|
use syntax_pos::{BytePos, FileMap};
|
|
@ -8,9 +8,9 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use rustc::hir::def_id::DefId;
|
use hir::def_id::DefId;
|
||||||
use rustc::ty::TyCtxt;
|
use ty::TyCtxt;
|
||||||
use rustc::util::nodemap::DefIdMap;
|
use util::nodemap::DefIdMap;
|
||||||
|
|
||||||
pub struct DefPathHashes<'a, 'tcx: 'a> {
|
pub struct DefPathHashes<'a, 'tcx: 'a> {
|
||||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
34
src/librustc/ich/mod.rs
Normal file
34
src/librustc/ich/mod.rs
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
// Copyright 2017 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 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
pub use self::fingerprint::Fingerprint;
|
||||||
|
pub use self::def_path_hash::DefPathHashes;
|
||||||
|
pub use self::caching_codemap_view::CachingCodemapView;
|
||||||
|
|
||||||
|
mod fingerprint;
|
||||||
|
mod def_path_hash;
|
||||||
|
mod caching_codemap_view;
|
||||||
|
|
||||||
|
pub const ATTR_DIRTY: &'static str = "rustc_dirty";
|
||||||
|
pub const ATTR_CLEAN: &'static str = "rustc_clean";
|
||||||
|
pub const ATTR_DIRTY_METADATA: &'static str = "rustc_metadata_dirty";
|
||||||
|
pub const ATTR_CLEAN_METADATA: &'static str = "rustc_metadata_clean";
|
||||||
|
pub const ATTR_IF_THIS_CHANGED: &'static str = "rustc_if_this_changed";
|
||||||
|
pub const ATTR_THEN_THIS_WOULD_NEED: &'static str = "rustc_then_this_would_need";
|
||||||
|
|
||||||
|
pub const IGNORED_ATTRIBUTES: &'static [&'static str] = &[
|
||||||
|
"cfg",
|
||||||
|
ATTR_IF_THIS_CHANGED,
|
||||||
|
ATTR_THEN_THIS_WOULD_NEED,
|
||||||
|
ATTR_DIRTY,
|
||||||
|
ATTR_CLEAN,
|
||||||
|
ATTR_DIRTY_METADATA,
|
||||||
|
ATTR_CLEAN_METADATA
|
||||||
|
];
|
|
@ -72,6 +72,7 @@ pub mod diagnostics;
|
||||||
pub mod cfg;
|
pub mod cfg;
|
||||||
pub mod dep_graph;
|
pub mod dep_graph;
|
||||||
pub mod hir;
|
pub mod hir;
|
||||||
|
pub mod ich;
|
||||||
pub mod infer;
|
pub mod infer;
|
||||||
pub mod lint;
|
pub mod lint;
|
||||||
|
|
||||||
|
|
|
@ -82,6 +82,7 @@ pub enum OutputType {
|
||||||
Bitcode,
|
Bitcode,
|
||||||
Assembly,
|
Assembly,
|
||||||
LlvmAssembly,
|
LlvmAssembly,
|
||||||
|
Mir,
|
||||||
Metadata,
|
Metadata,
|
||||||
Object,
|
Object,
|
||||||
Exe,
|
Exe,
|
||||||
|
@ -96,6 +97,7 @@ impl OutputType {
|
||||||
OutputType::Bitcode |
|
OutputType::Bitcode |
|
||||||
OutputType::Assembly |
|
OutputType::Assembly |
|
||||||
OutputType::LlvmAssembly |
|
OutputType::LlvmAssembly |
|
||||||
|
OutputType::Mir |
|
||||||
OutputType::Object |
|
OutputType::Object |
|
||||||
OutputType::Metadata => false,
|
OutputType::Metadata => false,
|
||||||
}
|
}
|
||||||
|
@ -106,6 +108,7 @@ impl OutputType {
|
||||||
OutputType::Bitcode => "llvm-bc",
|
OutputType::Bitcode => "llvm-bc",
|
||||||
OutputType::Assembly => "asm",
|
OutputType::Assembly => "asm",
|
||||||
OutputType::LlvmAssembly => "llvm-ir",
|
OutputType::LlvmAssembly => "llvm-ir",
|
||||||
|
OutputType::Mir => "mir",
|
||||||
OutputType::Object => "obj",
|
OutputType::Object => "obj",
|
||||||
OutputType::Metadata => "metadata",
|
OutputType::Metadata => "metadata",
|
||||||
OutputType::Exe => "link",
|
OutputType::Exe => "link",
|
||||||
|
@ -118,6 +121,7 @@ impl OutputType {
|
||||||
OutputType::Bitcode => "bc",
|
OutputType::Bitcode => "bc",
|
||||||
OutputType::Assembly => "s",
|
OutputType::Assembly => "s",
|
||||||
OutputType::LlvmAssembly => "ll",
|
OutputType::LlvmAssembly => "ll",
|
||||||
|
OutputType::Mir => "mir",
|
||||||
OutputType::Object => "o",
|
OutputType::Object => "o",
|
||||||
OutputType::Metadata => "rmeta",
|
OutputType::Metadata => "rmeta",
|
||||||
OutputType::DepInfo => "d",
|
OutputType::DepInfo => "d",
|
||||||
|
@ -172,6 +176,7 @@ impl OutputTypes {
|
||||||
OutputType::Bitcode |
|
OutputType::Bitcode |
|
||||||
OutputType::Assembly |
|
OutputType::Assembly |
|
||||||
OutputType::LlvmAssembly |
|
OutputType::LlvmAssembly |
|
||||||
|
OutputType::Mir |
|
||||||
OutputType::Object |
|
OutputType::Object |
|
||||||
OutputType::Exe => true,
|
OutputType::Exe => true,
|
||||||
OutputType::Metadata |
|
OutputType::Metadata |
|
||||||
|
@ -1370,6 +1375,7 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches)
|
||||||
let output_type = match parts.next().unwrap() {
|
let output_type = match parts.next().unwrap() {
|
||||||
"asm" => OutputType::Assembly,
|
"asm" => OutputType::Assembly,
|
||||||
"llvm-ir" => OutputType::LlvmAssembly,
|
"llvm-ir" => OutputType::LlvmAssembly,
|
||||||
|
"mir" => OutputType::Mir,
|
||||||
"llvm-bc" => OutputType::Bitcode,
|
"llvm-bc" => OutputType::Bitcode,
|
||||||
"obj" => OutputType::Object,
|
"obj" => OutputType::Object,
|
||||||
"metadata" => OutputType::Metadata,
|
"metadata" => OutputType::Metadata,
|
||||||
|
|
|
@ -509,18 +509,21 @@ impl<'a, 'gcx, 'tcx, W> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tcx, W>
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_region(&mut self, r: &'tcx ty::Region) -> bool {
|
fn visit_region(&mut self, r: &'tcx ty::Region) -> bool {
|
||||||
|
self.hash_discriminant_u8(r);
|
||||||
match *r {
|
match *r {
|
||||||
ty::ReErased => {
|
ty::ReErased |
|
||||||
self.hash::<u32>(0);
|
ty::ReStatic |
|
||||||
|
ty::ReEmpty => {
|
||||||
|
// No variant fields to hash for these ...
|
||||||
}
|
}
|
||||||
ty::ReLateBound(db, ty::BrAnon(i)) => {
|
ty::ReLateBound(db, ty::BrAnon(i)) => {
|
||||||
assert!(db.depth > 0);
|
self.hash(db.depth);
|
||||||
self.hash::<u32>(db.depth);
|
|
||||||
self.hash(i);
|
self.hash(i);
|
||||||
}
|
}
|
||||||
ty::ReStatic |
|
ty::ReEarlyBound(ty::EarlyBoundRegion { index, name }) => {
|
||||||
ty::ReEmpty |
|
self.hash(index);
|
||||||
ty::ReEarlyBound(..) |
|
self.hash(name.as_str());
|
||||||
|
}
|
||||||
ty::ReLateBound(..) |
|
ty::ReLateBound(..) |
|
||||||
ty::ReFree(..) |
|
ty::ReFree(..) |
|
||||||
ty::ReScope(..) |
|
ty::ReScope(..) |
|
||||||
|
|
|
@ -189,6 +189,13 @@ impl<I: Idx, T> IndexVec<I, T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<I: Idx, T: Clone> IndexVec<I, T> {
|
||||||
|
#[inline]
|
||||||
|
pub fn resize(&mut self, new_len: usize, value: T) {
|
||||||
|
self.raw.resize(new_len, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<I: Idx, T> Index<I> for IndexVec<I, T> {
|
impl<I: Idx, T> Index<I> for IndexVec<I, T> {
|
||||||
type Output = T;
|
type Output = T;
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
use rustc::hir::{self, map as hir_map};
|
use rustc::hir::{self, map as hir_map};
|
||||||
use rustc::hir::lowering::lower_crate;
|
use rustc::hir::lowering::lower_crate;
|
||||||
|
use rustc::ich::Fingerprint;
|
||||||
use rustc_data_structures::stable_hasher::StableHasher;
|
use rustc_data_structures::stable_hasher::StableHasher;
|
||||||
use rustc_mir as mir;
|
use rustc_mir as mir;
|
||||||
use rustc::session::{Session, CompileResult, compile_result_from_err_count};
|
use rustc::session::{Session, CompileResult, compile_result_from_err_count};
|
||||||
|
@ -25,7 +26,6 @@ use rustc::util::nodemap::NodeSet;
|
||||||
use rustc::util::fs::rename_or_copy_remove;
|
use rustc::util::fs::rename_or_copy_remove;
|
||||||
use rustc_borrowck as borrowck;
|
use rustc_borrowck as borrowck;
|
||||||
use rustc_incremental::{self, IncrementalHashesMap};
|
use rustc_incremental::{self, IncrementalHashesMap};
|
||||||
use rustc_incremental::ich::Fingerprint;
|
|
||||||
use rustc_resolve::{MakeGlobMap, Resolver};
|
use rustc_resolve::{MakeGlobMap, Resolver};
|
||||||
use rustc_metadata::creader::CrateLoader;
|
use rustc_metadata::creader::CrateLoader;
|
||||||
use rustc_metadata::cstore::{self, CStore};
|
use rustc_metadata::cstore::{self, CStore};
|
||||||
|
@ -209,6 +209,13 @@ pub fn compile_input(sess: &Session,
|
||||||
tcx.print_debug_stats();
|
tcx.print_debug_stats();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if tcx.sess.opts.output_types.contains_key(&OutputType::Mir) {
|
||||||
|
if let Err(e) = mir::transform::dump_mir::emit_mir(tcx, &outputs) {
|
||||||
|
sess.err(&format!("could not emit MIR: {}", e));
|
||||||
|
sess.abort_if_errors();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok((outputs, trans))
|
Ok((outputs, trans))
|
||||||
})??
|
})??
|
||||||
};
|
};
|
||||||
|
|
|
@ -52,13 +52,13 @@ use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc_data_structures::graph::{Direction, INCOMING, OUTGOING, NodeIndex};
|
use rustc_data_structures::graph::{Direction, INCOMING, OUTGOING, NodeIndex};
|
||||||
use rustc::hir;
|
use rustc::hir;
|
||||||
use rustc::hir::itemlikevisit::ItemLikeVisitor;
|
use rustc::hir::itemlikevisit::ItemLikeVisitor;
|
||||||
|
use rustc::ich::{ATTR_IF_THIS_CHANGED, ATTR_THEN_THIS_WOULD_NEED};
|
||||||
use graphviz::IntoCow;
|
use graphviz::IntoCow;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use syntax_pos::Span;
|
use syntax_pos::Span;
|
||||||
use {ATTR_IF_THIS_CHANGED, ATTR_THEN_THIS_WOULD_NEED};
|
|
||||||
|
|
||||||
pub fn assert_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
|
pub fn assert_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
|
||||||
let _ignore = tcx.dep_graph.in_ignore();
|
let _ignore = tcx.dep_graph.in_ignore();
|
||||||
|
|
|
@ -35,20 +35,16 @@ use rustc::hir;
|
||||||
use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId};
|
use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId};
|
||||||
use rustc::hir::intravisit as visit;
|
use rustc::hir::intravisit as visit;
|
||||||
use rustc::hir::intravisit::{Visitor, NestedVisitorMap};
|
use rustc::hir::intravisit::{Visitor, NestedVisitorMap};
|
||||||
|
use rustc::ich::{Fingerprint, DefPathHashes, CachingCodemapView};
|
||||||
use rustc::ty::TyCtxt;
|
use rustc::ty::TyCtxt;
|
||||||
use rustc_data_structures::stable_hasher::StableHasher;
|
use rustc_data_structures::stable_hasher::StableHasher;
|
||||||
use ich::Fingerprint;
|
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc::util::common::record_time;
|
use rustc::util::common::record_time;
|
||||||
use rustc::session::config::DebugInfoLevel::NoDebugInfo;
|
use rustc::session::config::DebugInfoLevel::NoDebugInfo;
|
||||||
|
|
||||||
use self::def_path_hash::DefPathHashes;
|
|
||||||
use self::svh_visitor::StrictVersionHashVisitor;
|
use self::svh_visitor::StrictVersionHashVisitor;
|
||||||
use self::caching_codemap_view::CachingCodemapView;
|
|
||||||
|
|
||||||
mod def_path_hash;
|
|
||||||
mod svh_visitor;
|
mod svh_visitor;
|
||||||
mod caching_codemap_view;
|
|
||||||
|
|
||||||
pub type IchHasher = StableHasher<Fingerprint>;
|
pub type IchHasher = StableHasher<Fingerprint>;
|
||||||
|
|
||||||
|
|
|
@ -26,23 +26,12 @@ use rustc::hir::*;
|
||||||
use rustc::hir::def::Def;
|
use rustc::hir::def::Def;
|
||||||
use rustc::hir::def_id::DefId;
|
use rustc::hir::def_id::DefId;
|
||||||
use rustc::hir::intravisit::{self as visit, Visitor};
|
use rustc::hir::intravisit::{self as visit, Visitor};
|
||||||
|
use rustc::ich::{DefPathHashes, CachingCodemapView, IGNORED_ATTRIBUTES};
|
||||||
use rustc::ty::TyCtxt;
|
use rustc::ty::TyCtxt;
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
|
|
||||||
use super::def_path_hash::DefPathHashes;
|
|
||||||
use super::caching_codemap_view::CachingCodemapView;
|
|
||||||
use super::IchHasher;
|
use super::IchHasher;
|
||||||
|
|
||||||
const IGNORED_ATTRIBUTES: &'static [&'static str] = &[
|
|
||||||
"cfg",
|
|
||||||
::ATTR_IF_THIS_CHANGED,
|
|
||||||
::ATTR_THEN_THIS_WOULD_NEED,
|
|
||||||
::ATTR_DIRTY,
|
|
||||||
::ATTR_CLEAN,
|
|
||||||
::ATTR_DIRTY_METADATA,
|
|
||||||
::ATTR_CLEAN_METADATA
|
|
||||||
];
|
|
||||||
|
|
||||||
pub struct StrictVersionHashVisitor<'a, 'hash: 'a, 'tcx: 'hash> {
|
pub struct StrictVersionHashVisitor<'a, 'hash: 'a, 'tcx: 'hash> {
|
||||||
pub tcx: TyCtxt<'hash, 'tcx, 'tcx>,
|
pub tcx: TyCtxt<'hash, 'tcx, 'tcx>,
|
||||||
pub st: &'a mut IchHasher,
|
pub st: &'a mut IchHasher,
|
||||||
|
|
|
@ -36,17 +36,9 @@ extern crate serialize as rustc_serialize;
|
||||||
extern crate syntax;
|
extern crate syntax;
|
||||||
extern crate syntax_pos;
|
extern crate syntax_pos;
|
||||||
|
|
||||||
const ATTR_DIRTY: &'static str = "rustc_dirty";
|
|
||||||
const ATTR_CLEAN: &'static str = "rustc_clean";
|
|
||||||
const ATTR_DIRTY_METADATA: &'static str = "rustc_metadata_dirty";
|
|
||||||
const ATTR_CLEAN_METADATA: &'static str = "rustc_metadata_clean";
|
|
||||||
const ATTR_IF_THIS_CHANGED: &'static str = "rustc_if_this_changed";
|
|
||||||
const ATTR_THEN_THIS_WOULD_NEED: &'static str = "rustc_then_this_would_need";
|
|
||||||
|
|
||||||
mod assert_dep_graph;
|
mod assert_dep_graph;
|
||||||
mod calculate_svh;
|
mod calculate_svh;
|
||||||
mod persist;
|
mod persist;
|
||||||
pub mod ich;
|
|
||||||
|
|
||||||
pub use assert_dep_graph::assert_dep_graph;
|
pub use assert_dep_graph::assert_dep_graph;
|
||||||
pub use calculate_svh::compute_incremental_hashes_map;
|
pub use calculate_svh::compute_incremental_hashes_map;
|
||||||
|
|
|
@ -12,9 +12,9 @@
|
||||||
|
|
||||||
use rustc::dep_graph::{DepNode, WorkProduct, WorkProductId};
|
use rustc::dep_graph::{DepNode, WorkProduct, WorkProductId};
|
||||||
use rustc::hir::def_id::DefIndex;
|
use rustc::hir::def_id::DefIndex;
|
||||||
|
use rustc::ich::Fingerprint;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use ich::Fingerprint;
|
|
||||||
|
|
||||||
use super::directory::DefPathIndex;
|
use super::directory::DefPathIndex;
|
||||||
|
|
||||||
|
|
|
@ -47,13 +47,12 @@ use rustc::hir;
|
||||||
use rustc::hir::def_id::DefId;
|
use rustc::hir::def_id::DefId;
|
||||||
use rustc::hir::itemlikevisit::ItemLikeVisitor;
|
use rustc::hir::itemlikevisit::ItemLikeVisitor;
|
||||||
use rustc::hir::intravisit;
|
use rustc::hir::intravisit;
|
||||||
|
use rustc::ich::{Fingerprint, ATTR_DIRTY, ATTR_CLEAN, ATTR_DIRTY_METADATA,
|
||||||
|
ATTR_CLEAN_METADATA};
|
||||||
use syntax::ast::{self, Attribute, NestedMetaItem};
|
use syntax::ast::{self, Attribute, NestedMetaItem};
|
||||||
use rustc_data_structures::fx::{FxHashSet, FxHashMap};
|
use rustc_data_structures::fx::{FxHashSet, FxHashMap};
|
||||||
use syntax_pos::Span;
|
use syntax_pos::Span;
|
||||||
use rustc::ty::TyCtxt;
|
use rustc::ty::TyCtxt;
|
||||||
use ich::Fingerprint;
|
|
||||||
|
|
||||||
use {ATTR_DIRTY, ATTR_CLEAN, ATTR_DIRTY_METADATA, ATTR_CLEAN_METADATA};
|
|
||||||
|
|
||||||
const LABEL: &'static str = "label";
|
const LABEL: &'static str = "label";
|
||||||
const CFG: &'static str = "cfg";
|
const CFG: &'static str = "cfg";
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
use rustc::dep_graph::DepNode;
|
use rustc::dep_graph::DepNode;
|
||||||
use rustc::hir::def_id::{CrateNum, DefId};
|
use rustc::hir::def_id::{CrateNum, DefId};
|
||||||
use rustc::hir::svh::Svh;
|
use rustc::hir::svh::Svh;
|
||||||
|
use rustc::ich::Fingerprint;
|
||||||
use rustc::ty::TyCtxt;
|
use rustc::ty::TyCtxt;
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_data_structures::flock;
|
use rustc_data_structures::flock;
|
||||||
|
@ -18,7 +19,6 @@ use rustc_serialize::Decodable;
|
||||||
use rustc_serialize::opaque::Decoder;
|
use rustc_serialize::opaque::Decoder;
|
||||||
|
|
||||||
use IncrementalHashesMap;
|
use IncrementalHashesMap;
|
||||||
use ich::Fingerprint;
|
|
||||||
use super::data::*;
|
use super::data::*;
|
||||||
use super::fs::*;
|
use super::fs::*;
|
||||||
use super::file_format;
|
use super::file_format;
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
use rustc::dep_graph::{DepNode, WorkProductId};
|
use rustc::dep_graph::{DepNode, WorkProductId};
|
||||||
use rustc::hir::def_id::DefId;
|
use rustc::hir::def_id::DefId;
|
||||||
use rustc::hir::svh::Svh;
|
use rustc::hir::svh::Svh;
|
||||||
|
use rustc::ich::Fingerprint;
|
||||||
use rustc::session::Session;
|
use rustc::session::Session;
|
||||||
use rustc::ty::TyCtxt;
|
use rustc::ty::TyCtxt;
|
||||||
use rustc_data_structures::fx::{FxHashSet, FxHashMap};
|
use rustc_data_structures::fx::{FxHashSet, FxHashMap};
|
||||||
|
@ -22,7 +23,6 @@ use std::path::{Path};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use IncrementalHashesMap;
|
use IncrementalHashesMap;
|
||||||
use ich::Fingerprint;
|
|
||||||
use super::data::*;
|
use super::data::*;
|
||||||
use super::directory::*;
|
use super::directory::*;
|
||||||
use super::dirty_clean;
|
use super::dirty_clean;
|
||||||
|
|
|
@ -10,11 +10,11 @@
|
||||||
|
|
||||||
use rustc::dep_graph::{DepGraphQuery, DepNode};
|
use rustc::dep_graph::{DepGraphQuery, DepNode};
|
||||||
use rustc::hir::def_id::DefId;
|
use rustc::hir::def_id::DefId;
|
||||||
|
use rustc::ich::Fingerprint;
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_data_structures::graph::{Graph, NodeIndex};
|
use rustc_data_structures::graph::{Graph, NodeIndex};
|
||||||
|
|
||||||
use super::hash::*;
|
use super::hash::*;
|
||||||
use ich::Fingerprint;
|
|
||||||
|
|
||||||
mod compress;
|
mod compress;
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
use rustc::dep_graph::DepNode;
|
use rustc::dep_graph::DepNode;
|
||||||
use rustc::hir::def_id::DefId;
|
use rustc::hir::def_id::DefId;
|
||||||
use rustc::hir::svh::Svh;
|
use rustc::hir::svh::Svh;
|
||||||
|
use rustc::ich::Fingerprint;
|
||||||
use rustc::session::Session;
|
use rustc::session::Session;
|
||||||
use rustc::ty::TyCtxt;
|
use rustc::ty::TyCtxt;
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
|
@ -23,7 +24,6 @@ use std::fs::{self, File};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use IncrementalHashesMap;
|
use IncrementalHashesMap;
|
||||||
use ich::Fingerprint;
|
|
||||||
use super::data::*;
|
use super::data::*;
|
||||||
use super::directory::*;
|
use super::directory::*;
|
||||||
use super::hash::*;
|
use super::hash::*;
|
||||||
|
|
|
@ -236,7 +236,8 @@ impl<'a> CrateLoader<'a> {
|
||||||
// path (this is a top-level dependency) as we don't want to
|
// path (this is a top-level dependency) as we don't want to
|
||||||
// implicitly load anything inside the dependency lookup path.
|
// implicitly load anything inside the dependency lookup path.
|
||||||
let prev_kind = source.dylib.as_ref().or(source.rlib.as_ref())
|
let prev_kind = source.dylib.as_ref().or(source.rlib.as_ref())
|
||||||
.unwrap().1;
|
.or(source.rmeta.as_ref())
|
||||||
|
.expect("No sources for crate").1;
|
||||||
if ret.is_none() && (prev_kind == kind || prev_kind == PathKind::All) {
|
if ret.is_none() && (prev_kind == kind || prev_kind == PathKind::All) {
|
||||||
ret = Some(cnum);
|
ret = Some(cnum);
|
||||||
}
|
}
|
||||||
|
|
|
@ -558,7 +558,6 @@ impl<'a, 'tcx> CrateMetadata {
|
||||||
EntryKind::Union(_, _) => ty::AdtKind::Union,
|
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 mut ctor_index = None;
|
|
||||||
let variants = if let ty::AdtKind::Enum = kind {
|
let variants = if let ty::AdtKind::Enum = kind {
|
||||||
item.children
|
item.children
|
||||||
.decode(self)
|
.decode(self)
|
||||||
|
@ -570,8 +569,7 @@ impl<'a, 'tcx> CrateMetadata {
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
} else {
|
} else {
|
||||||
let (variant, struct_ctor) = self.get_variant(&item, item_id, tcx);
|
let (variant, _struct_ctor) = self.get_variant(&item, item_id, tcx);
|
||||||
ctor_index = struct_ctor;
|
|
||||||
vec![variant]
|
vec![variant]
|
||||||
};
|
};
|
||||||
let (kind, repr) = match item.kind {
|
let (kind, repr) = match item.kind {
|
||||||
|
@ -581,13 +579,7 @@ impl<'a, 'tcx> CrateMetadata {
|
||||||
_ => bug!("get_adt_def called on a non-ADT {:?}", did),
|
_ => bug!("get_adt_def called on a non-ADT {:?}", did),
|
||||||
};
|
};
|
||||||
|
|
||||||
let adt = tcx.alloc_adt_def(did, kind, variants, repr);
|
tcx.alloc_adt_def(did, kind, variants, repr)
|
||||||
if let Some(ctor_index) = ctor_index {
|
|
||||||
// Make adt definition available through constructor id as well.
|
|
||||||
tcx.maps.adt_def.borrow_mut().insert(self.local_def_id(ctor_index), adt);
|
|
||||||
}
|
|
||||||
|
|
||||||
adt
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_predicates(&self,
|
pub fn get_predicates(&self,
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
use schema::*;
|
use schema::*;
|
||||||
|
|
||||||
use rustc::hir::def_id::{DefId, DefIndex};
|
use rustc::hir::def_id::{DefId, DefIndex, DefIndexAddressSpace};
|
||||||
use std::io::{Cursor, Write};
|
use std::io::{Cursor, Write};
|
||||||
use std::slice;
|
use std::slice;
|
||||||
use std::u32;
|
use std::u32;
|
||||||
|
@ -23,12 +23,15 @@ use std::u32;
|
||||||
/// appropriate spot by calling `record_position`. We should never
|
/// appropriate spot by calling `record_position`. We should never
|
||||||
/// visit the same index twice.
|
/// visit the same index twice.
|
||||||
pub struct Index {
|
pub struct Index {
|
||||||
positions: Vec<u32>,
|
positions: [Vec<u32>; 2]
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Index {
|
impl Index {
|
||||||
pub fn new(max_index: usize) -> Index {
|
pub fn new((max_index_lo, max_index_hi): (usize, usize)) -> Index {
|
||||||
Index { positions: vec![u32::MAX; max_index] }
|
Index {
|
||||||
|
positions: [vec![u32::MAX; max_index_lo],
|
||||||
|
vec![u32::MAX; max_index_hi]],
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn record(&mut self, def_id: DefId, entry: Lazy<Entry>) {
|
pub fn record(&mut self, def_id: DefId, entry: Lazy<Entry>) {
|
||||||
|
@ -37,24 +40,31 @@ impl Index {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn record_index(&mut self, item: DefIndex, entry: Lazy<Entry>) {
|
pub fn record_index(&mut self, item: DefIndex, entry: Lazy<Entry>) {
|
||||||
let item = item.as_usize();
|
|
||||||
|
|
||||||
assert!(entry.position < (u32::MAX as usize));
|
assert!(entry.position < (u32::MAX as usize));
|
||||||
let position = entry.position as u32;
|
let position = entry.position as u32;
|
||||||
|
let space_index = item.address_space().index();
|
||||||
|
let array_index = item.as_array_index();
|
||||||
|
|
||||||
assert!(self.positions[item] == u32::MAX,
|
assert!(self.positions[space_index][array_index] == u32::MAX,
|
||||||
"recorded position for item {:?} twice, first at {:?} and now at {:?}",
|
"recorded position for item {:?} twice, first at {:?} and now at {:?}",
|
||||||
item,
|
item,
|
||||||
self.positions[item],
|
self.positions[space_index][array_index],
|
||||||
position);
|
position);
|
||||||
|
|
||||||
self.positions[item] = position.to_le();
|
self.positions[space_index][array_index] = position.to_le();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_index(&self, buf: &mut Cursor<Vec<u8>>) -> LazySeq<Index> {
|
pub fn write_index(&self, buf: &mut Cursor<Vec<u8>>) -> LazySeq<Index> {
|
||||||
let pos = buf.position();
|
let pos = buf.position();
|
||||||
buf.write_all(words_to_bytes(&self.positions)).unwrap();
|
|
||||||
LazySeq::with_position_and_length(pos as usize, self.positions.len())
|
// First we write the length of the lower range ...
|
||||||
|
buf.write_all(words_to_bytes(&[self.positions[0].len() as u32])).unwrap();
|
||||||
|
// ... then the values in the lower range ...
|
||||||
|
buf.write_all(words_to_bytes(&self.positions[0][..])).unwrap();
|
||||||
|
// ... then the values in the higher range.
|
||||||
|
buf.write_all(words_to_bytes(&self.positions[1][..])).unwrap();
|
||||||
|
LazySeq::with_position_and_length(pos as usize,
|
||||||
|
self.positions[0].len() + self.positions[1].len() + 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,7 +80,18 @@ impl<'tcx> LazySeq<Index> {
|
||||||
index,
|
index,
|
||||||
words.len());
|
words.len());
|
||||||
|
|
||||||
let position = u32::from_le(words[index].get());
|
let positions = match def_index.address_space() {
|
||||||
|
DefIndexAddressSpace::Low => &words[1..],
|
||||||
|
DefIndexAddressSpace::High => {
|
||||||
|
// This is a DefIndex in the higher range, so find out where
|
||||||
|
// that starts:
|
||||||
|
let lo_count = u32::from_le(words[0].get()) as usize;
|
||||||
|
&words[lo_count + 1 .. ]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let array_index = def_index.as_array_index();
|
||||||
|
let position = u32::from_le(positions[array_index].get());
|
||||||
if position == u32::MAX {
|
if position == u32::MAX {
|
||||||
debug!("Index::lookup: position=u32::MAX");
|
debug!("Index::lookup: position=u32::MAX");
|
||||||
None
|
None
|
||||||
|
@ -84,14 +105,26 @@ impl<'tcx> LazySeq<Index> {
|
||||||
bytes: &'a [u8])
|
bytes: &'a [u8])
|
||||||
-> impl Iterator<Item = (DefIndex, Lazy<Entry<'tcx>>)> + 'a {
|
-> impl Iterator<Item = (DefIndex, Lazy<Entry<'tcx>>)> + 'a {
|
||||||
let words = &bytes_to_words(&bytes[self.position..])[..self.len];
|
let words = &bytes_to_words(&bytes[self.position..])[..self.len];
|
||||||
words.iter().map(|word| word.get()).enumerate().filter_map(|(index, position)| {
|
let lo_count = u32::from_le(words[0].get()) as usize;
|
||||||
if position == u32::MAX {
|
let lo = &words[1 .. lo_count + 1];
|
||||||
|
let hi = &words[1 + lo_count ..];
|
||||||
|
|
||||||
|
lo.iter().map(|word| word.get()).enumerate().filter_map(|(index, pos)| {
|
||||||
|
if pos == u32::MAX {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
let position = u32::from_le(position) as usize;
|
let pos = u32::from_le(pos) as usize;
|
||||||
Some((DefIndex::new(index), Lazy::with_position(position)))
|
Some((DefIndex::new(index), Lazy::with_position(pos)))
|
||||||
}
|
}
|
||||||
})
|
}).chain(hi.iter().map(|word| word.get()).enumerate().filter_map(|(index, pos)| {
|
||||||
|
if pos == u32::MAX {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
let pos = u32::from_le(pos) as usize;
|
||||||
|
Some((DefIndex::new(index + DefIndexAddressSpace::High.start()),
|
||||||
|
Lazy::with_position(pos)))
|
||||||
|
}
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -90,7 +90,7 @@ impl<'a, 'b, 'tcx> DerefMut for IndexBuilder<'a, 'b, 'tcx> {
|
||||||
impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
|
impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
|
||||||
pub fn new(ecx: &'a mut EncodeContext<'b, 'tcx>) -> Self {
|
pub fn new(ecx: &'a mut EncodeContext<'b, 'tcx>) -> Self {
|
||||||
IndexBuilder {
|
IndexBuilder {
|
||||||
items: Index::new(ecx.tcx.hir.num_local_def_ids()),
|
items: Index::new(ecx.tcx.hir.definitions().def_index_counts_lo_hi()),
|
||||||
ecx: ecx,
|
ecx: ecx,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,10 @@
|
||||||
//! This pass just dumps MIR at a specified point.
|
//! This pass just dumps MIR at a specified point.
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io;
|
||||||
|
|
||||||
|
use rustc::session::config::{OutputFilenames, OutputType};
|
||||||
use rustc::ty::TyCtxt;
|
use rustc::ty::TyCtxt;
|
||||||
use rustc::mir::*;
|
use rustc::mir::*;
|
||||||
use rustc::mir::transform::{Pass, MirPass, MirPassHook, MirSource};
|
use rustc::mir::transform::{Pass, MirPass, MirPassHook, MirSource};
|
||||||
|
@ -70,3 +73,14 @@ impl<'tcx> MirPassHook<'tcx> for DumpMir {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'b> Pass for DumpMir {}
|
impl<'b> Pass for DumpMir {}
|
||||||
|
|
||||||
|
pub fn emit_mir<'a, 'tcx>(
|
||||||
|
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
|
outputs: &OutputFilenames)
|
||||||
|
-> io::Result<()>
|
||||||
|
{
|
||||||
|
let path = outputs.path(OutputType::Mir);
|
||||||
|
let mut f = File::create(&path)?;
|
||||||
|
mir_util::write_mir_pretty(tcx, tcx.maps.mir.borrow().keys().into_iter(), &mut f)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
//! care erasing regions all over the place.
|
//! care erasing regions all over the place.
|
||||||
|
|
||||||
use rustc::ty::subst::Substs;
|
use rustc::ty::subst::Substs;
|
||||||
use rustc::ty::{Ty, TyCtxt};
|
use rustc::ty::{Ty, TyCtxt, ReErased, ClosureSubsts};
|
||||||
use rustc::mir::*;
|
use rustc::mir::*;
|
||||||
use rustc::mir::visit::MutVisitor;
|
use rustc::mir::visit::MutVisitor;
|
||||||
use rustc::mir::transform::{MirPass, MirSource, Pass};
|
use rustc::mir::transform::{MirPass, MirSource, Pass};
|
||||||
|
@ -39,6 +39,32 @@ impl<'a, 'tcx> MutVisitor<'tcx> for EraseRegionsVisitor<'a, 'tcx> {
|
||||||
fn visit_substs(&mut self, substs: &mut &'tcx Substs<'tcx>) {
|
fn visit_substs(&mut self, substs: &mut &'tcx Substs<'tcx>) {
|
||||||
*substs = self.tcx.erase_regions(&{*substs});
|
*substs = self.tcx.erase_regions(&{*substs});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>, location: Location) {
|
||||||
|
match *rvalue {
|
||||||
|
Rvalue::Ref(ref mut r, _, _) => {
|
||||||
|
*r = self.tcx.mk_region(ReErased);
|
||||||
|
}
|
||||||
|
Rvalue::Use(..) |
|
||||||
|
Rvalue::Repeat(..) |
|
||||||
|
Rvalue::Len(..) |
|
||||||
|
Rvalue::Cast(..) |
|
||||||
|
Rvalue::BinaryOp(..) |
|
||||||
|
Rvalue::CheckedBinaryOp(..) |
|
||||||
|
Rvalue::UnaryOp(..) |
|
||||||
|
Rvalue::Discriminant(..) |
|
||||||
|
Rvalue::Box(..) |
|
||||||
|
Rvalue::Aggregate(..) => {
|
||||||
|
// These variants don't contain regions.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.super_rvalue(rvalue, location);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_closure_substs(&mut self,
|
||||||
|
substs: &mut ClosureSubsts<'tcx>) {
|
||||||
|
*substs = self.tcx.erase_regions(substs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct EraseRegions;
|
pub struct EraseRegions;
|
||||||
|
|
|
@ -91,6 +91,9 @@ pub fn write_mir_pretty<'a, 'b, 'tcx, I>(tcx: TyCtxt<'b, 'tcx, 'tcx>,
|
||||||
-> io::Result<()>
|
-> io::Result<()>
|
||||||
where I: Iterator<Item=DefId>, 'tcx: 'a
|
where I: Iterator<Item=DefId>, 'tcx: 'a
|
||||||
{
|
{
|
||||||
|
writeln!(w, "// WARNING: This output format is intended for human consumers only")?;
|
||||||
|
writeln!(w, "// and is subject to change without notice. Knock yourself out.")?;
|
||||||
|
|
||||||
let mut first = true;
|
let mut first = true;
|
||||||
for def_id in iter.filter(DefId::is_local) {
|
for def_id in iter.filter(DefId::is_local) {
|
||||||
let mir = &tcx.item_mir(def_id);
|
let mir = &tcx.item_mir(def_id);
|
||||||
|
|
|
@ -741,6 +741,7 @@ pub fn run_passes(sess: &Session,
|
||||||
modules_config.emit_obj = true;
|
modules_config.emit_obj = true;
|
||||||
metadata_config.emit_obj = true;
|
metadata_config.emit_obj = true;
|
||||||
},
|
},
|
||||||
|
OutputType::Mir => {}
|
||||||
OutputType::DepInfo => {}
|
OutputType::DepInfo => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -880,6 +881,7 @@ pub fn run_passes(sess: &Session,
|
||||||
user_wants_objects = true;
|
user_wants_objects = true;
|
||||||
copy_if_one_unit(OutputType::Object, true);
|
copy_if_one_unit(OutputType::Object, true);
|
||||||
}
|
}
|
||||||
|
OutputType::Mir |
|
||||||
OutputType::Metadata |
|
OutputType::Metadata |
|
||||||
OutputType::Exe |
|
OutputType::Exe |
|
||||||
OutputType::DepInfo => {}
|
OutputType::DepInfo => {}
|
||||||
|
|
|
@ -689,12 +689,6 @@ fn adt_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
|
let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
|
||||||
let item = match tcx.hir.get(node_id) {
|
let item = match tcx.hir.get(node_id) {
|
||||||
NodeItem(item) => item,
|
NodeItem(item) => item,
|
||||||
|
|
||||||
// Make adt definition available through constructor id as well.
|
|
||||||
NodeStructCtor(_) => {
|
|
||||||
return tcx.lookup_adt_def(tcx.hir.get_parent_did(node_id));
|
|
||||||
}
|
|
||||||
|
|
||||||
_ => bug!()
|
_ => bug!()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ use abi::Abi;
|
||||||
use ext::hygiene::SyntaxContext;
|
use ext::hygiene::SyntaxContext;
|
||||||
use print::pprust;
|
use print::pprust;
|
||||||
use ptr::P;
|
use ptr::P;
|
||||||
|
use rustc_data_structures::indexed_vec;
|
||||||
use symbol::{Symbol, keywords};
|
use symbol::{Symbol, keywords};
|
||||||
use tokenstream::{ThinTokenStream, TokenStream};
|
use tokenstream::{ThinTokenStream, TokenStream};
|
||||||
|
|
||||||
|
@ -275,6 +276,16 @@ impl serialize::UseSpecializedDecodable for NodeId {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl indexed_vec::Idx for NodeId {
|
||||||
|
fn new(idx: usize) -> Self {
|
||||||
|
NodeId::new(idx)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn index(self) -> usize {
|
||||||
|
self.as_usize()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Node id used to represent the root of the crate.
|
/// Node id used to represent the root of the crate.
|
||||||
pub const CRATE_NODE_ID: NodeId = NodeId(0);
|
pub const CRATE_NODE_ID: NodeId = NodeId(0);
|
||||||
|
|
||||||
|
|
|
@ -178,17 +178,9 @@ impl<'a, 'b> Folder for PlaceholderExpander<'a, 'b> {
|
||||||
block.stmts = block.stmts.move_flat_map(|mut stmt| {
|
block.stmts = block.stmts.move_flat_map(|mut stmt| {
|
||||||
remaining_stmts -= 1;
|
remaining_stmts -= 1;
|
||||||
|
|
||||||
match stmt.node {
|
if self.monotonic {
|
||||||
// Avoid wasting a node id on a trailing expression statement,
|
assert_eq!(stmt.id, ast::DUMMY_NODE_ID);
|
||||||
// which shares a HIR node with the expression itself.
|
stmt.id = self.cx.resolver.next_node_id();
|
||||||
ast::StmtKind::Expr(ref expr) if remaining_stmts == 0 => stmt.id = expr.id,
|
|
||||||
|
|
||||||
_ if self.monotonic => {
|
|
||||||
assert_eq!(stmt.id, ast::DUMMY_NODE_ID);
|
|
||||||
stmt.id = self.cx.resolver.next_node_id();
|
|
||||||
}
|
|
||||||
|
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(stmt)
|
Some(stmt)
|
||||||
|
|
|
@ -18,7 +18,7 @@ trait SomeTrait { }
|
||||||
|
|
||||||
// Bounds on object types:
|
// Bounds on object types:
|
||||||
|
|
||||||
struct Foo<'a,'b,'c> { //~ ERROR parameter `'b` is never used
|
struct Foo<'a,'b,'c> { //~ ERROR parameter `'c` is never used
|
||||||
// All of these are ok, because we can derive exactly one bound:
|
// All of these are ok, because we can derive exactly one bound:
|
||||||
a: Box<IsStatic>,
|
a: Box<IsStatic>,
|
||||||
b: Box<Is<'static>>,
|
b: Box<Is<'static>>,
|
||||||
|
|
11
src/test/run-make/issue-40535/Makefile
Normal file
11
src/test/run-make/issue-40535/Makefile
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
# The ICE occurred in the following situation:
|
||||||
|
# * `foo` declares `extern crate bar, baz`, depends only on `bar` (forgetting `baz` in `Cargo.toml`)
|
||||||
|
# * `bar` declares and depends on `extern crate baz`
|
||||||
|
# * All crates built in metadata-only mode (`cargo check`)
|
||||||
|
all:
|
||||||
|
# cc https://github.com/rust-lang/rust/issues/40623
|
||||||
|
$(RUSTC) baz.rs --emit=metadata --out-dir=$(TMPDIR)
|
||||||
|
$(RUSTC) bar.rs --emit=metadata --extern baz=$(TMPDIR)/libbaz.rmeta --out-dir=$(TMPDIR)
|
||||||
|
$(RUSTC) foo.rs --emit=metadata --extern bar=$(TMPDIR)/libbar.rmeta --out-dir=$(TMPDIR) 2>&1 | \
|
||||||
|
grep -vq "unexpectedly panicked"
|
||||||
|
# ^ Succeeds if it doesn't find the ICE message
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
||||||
// file at the top-level directory of this distribution and at
|
// file at the top-level directory of this distribution and at
|
||||||
// http://rust-lang.org/COPYRIGHT.
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
//
|
//
|
||||||
|
@ -8,6 +8,6 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
pub use self::fingerprint::Fingerprint;
|
#![crate_type = "lib"]
|
||||||
|
|
||||||
mod fingerprint;
|
extern crate baz;
|
11
src/test/run-make/issue-40535/baz.rs
Normal file
11
src/test/run-make/issue-40535/baz.rs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
// Copyright 2017 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 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
#![crate_type = "lib"]
|
14
src/test/run-make/issue-40535/foo.rs
Normal file
14
src/test/run-make/issue-40535/foo.rs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
// Copyright 2017 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 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
#![crate_type = "lib"]
|
||||||
|
|
||||||
|
extern crate bar;
|
||||||
|
extern crate baz;
|
Loading…
Add table
Reference in a new issue