Handle DefPath hashing centrally as part of DefPathTable (+ save work during SVH calculation)
In almost all cases where we construct a `DefPath`, we just hash it and throw it away again immediately.
With this PR, the compiler will immediately compute and store the hash for each `DefPath` as it is allocated. This way we
+ can get rid of any subsequent `DefPath` hash caching (e.g. the `DefPathHashes`),
+ don't need to allocate a transient `Vec` for holding the `DefPath` (although I'm always surprised how little these small, dynamic allocations seem to hurt performance), and
+ we don't hash `DefPath` prefixes over and over again.
That last part is because we construct the hash for `prefix::foo` by hashing `(hash(prefix), foo)` instead of hashing every component of prefix.
The last commit of this PR is pretty neat, I think:
```
The SVH (Strict Version Hash) of a crate is currently computed
by hashing the ICHes (Incremental Computation Hashes) of the
crate's HIR. This is fine, expect that for incr. comp. we compute
two ICH values for each HIR item, one for the complete item and
one that just includes the item's interface. The two hashes are
are needed for dependency tracking but if we are compiling
non-incrementally and just need the ICH values for the SVH,
one of them is enough, giving us the opportunity to save some
work in this case.
```
r? @nikomatsakis
This PR depends on https://github.com/rust-lang/rust/pull/40878 to be merged first (you can ignore the first commit for reviewing, that's just https://github.com/rust-lang/rust/pull/40878).
copy(&build.src.join(item), &dst_src.join(item));
}
- // Get cargo-vendor installed, if it isn't already.
- let mut has_cargo_vendor = false;
- let mut cmd = Command::new(&build.cargo);
- for line in output(cmd.arg("install").arg("--list")).lines() {
- has_cargo_vendor |= line.starts_with("cargo-vendor ");
- }
- if !has_cargo_vendor {
+ // If we're building from git sources, we need to vendor a complete distribution.
+ if build.src_is_git {
+ // Get cargo-vendor installed, if it isn't already.
+ let mut has_cargo_vendor = false;
+ let mut cmd = Command::new(&build.cargo);
+ for line in output(cmd.arg("install").arg("--list")).lines() {
+ has_cargo_vendor |= line.starts_with("cargo-vendor ");
+ }
+ if !has_cargo_vendor {
+ let mut cmd = Command::new(&build.cargo);
+ cmd.arg("install")
+ .arg("--force")
+ .arg("--debug")
+ .arg("--vers").arg(CARGO_VENDOR_VERSION)
+ .arg("cargo-vendor")
+ .env("RUSTC", &build.rustc);
+ build.run(&mut cmd);
+ }
+
+ // Vendor all Cargo dependencies
let mut cmd = Command::new(&build.cargo);
- cmd.arg("install")
- .arg("--force")
- .arg("--debug")
- .arg("--vers").arg(CARGO_VENDOR_VERSION)
- .arg("cargo-vendor")
- .env("RUSTC", &build.rustc);
+ cmd.arg("vendor")
+ .current_dir(&dst_src.join("src"));
build.run(&mut cmd);
}
- // Vendor all Cargo dependencies
- let mut cmd = Command::new(&build.cargo);
- cmd.arg("vendor")
- .current_dir(&dst_src.join("src"));
- build.run(&mut cmd);
-
// Create source tarball in rust-installer format
let mut cmd = Command::new(SH_CMD);
cmd.arg(sanitize_sh(&build.src.join("src/rust-installer/gen-installer.sh")))
cxx: HashMap<String, gcc::Tool>,
crates: HashMap<String, Crate>,
is_sudo: bool,
+ src_is_git: bool,
}
#[derive(Debug)]
};
let rust_info = channel::GitInfo::new(&src);
let cargo_info = channel::GitInfo::new(&src.join("cargo"));
+ let src_is_git = src.join(".git").exists();
Build {
flags: flags,
lldb_version: None,
lldb_python_dir: None,
is_sudo: is_sudo,
+ src_is_git: src_is_git,
}
}
OutOfSync,
}
- if !self.config.submodules {
- return
- }
- if fs::metadata(self.src.join(".git")).is_err() {
+ if !self.src_is_git || !self.config.submodules {
return
}
let git = || {
// If we've got a git directory we're gona need git to update
// submodules and learn about various other aspects.
- if fs::metadata(build.src.join(".git")).is_ok() {
+ if build.src_is_git {
need_cmd("git".as_ref());
}
// makes all other generics or inline functions that it references
// reachable as well.
-use dep_graph::DepNode;
use hir::map as hir_map;
use hir::def::Def;
-use hir::def_id::DefId;
+use hir::def_id::{DefId, CrateNum};
use ty::{self, TyCtxt};
+use ty::maps::Providers;
use middle::privacy;
use session::config;
use util::nodemap::{NodeSet, FxHashSet};
}
pub fn find_reachable<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> NodeSet {
- let _task = tcx.dep_graph.in_task(DepNode::Reachability);
+ ty::queries::reachable_set::get(tcx, DUMMY_SP, LOCAL_CRATE)
+}
+
+fn reachable_set<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum) -> NodeSet {
+ debug_assert!(crate_num == LOCAL_CRATE);
let access_levels = &ty::queries::privacy_access_levels::get(tcx, DUMMY_SP, LOCAL_CRATE);
// Return the set of reachable symbols.
reachable_context.reachable_symbols
}
+
+pub fn provide(providers: &mut Providers) {
+ *providers = Providers {
+ reachable_set,
+ ..*providers
+ };
+}
use mir;
use session::CompileResult;
use ty::{self, CrateInherentImpls, Ty, TyCtxt};
+use util::nodemap::NodeSet;
use rustc_data_structures::indexed_vec::IndexVec;
use std::cell::{RefCell, RefMut};
}
}
+impl<'tcx> QueryDescription for queries::reachable_set<'tcx> {
+ fn describe(_: TyCtxt, _: CrateNum) -> String {
+ format!("reachability")
+ }
+}
macro_rules! define_maps {
(<$tcx:tt>
/// Performs the privacy check and computes "access levels".
pub privacy_access_levels: PrivacyAccessLevels(CrateNum) -> Rc<AccessLevels>,
+ pub reachable_set: reachability_dep_node(CrateNum) -> NodeSet,
+
pub mir_shims: mir_shim(ty::InstanceDef<'tcx>) -> &'tcx RefCell<mir::Mir<'tcx>>
}
DepNode::Coherence
}
+fn reachability_dep_node(_: CrateNum) -> DepNode<DefId> {
+ DepNode::Reachability
+}
+
fn mir_shim(instance: ty::InstanceDef) -> DepNode<DefId> {
instance.dep_node()
}
ALIASABLE(LV, MQ)
```
-### Checking mutability of immutable pointer types
+### Checking aliasability of immutable pointer types
Immutable pointer types like `&T` are aliasable, and hence can only be
borrowed immutably:
TYPE(LV) = &Ty
```
-### Checking mutability of mutable pointer types
+### Checking aliasability of mutable pointer types
`&mut T` can be frozen, so it is acceptable to borrow it as either imm or mut:
```rust
// Test region-reborrow-from-shorter-mut-ref.rs:
-fn copy_pointer<'a,'b,T>(x: &'a mut &'b mut T) -> &'b mut T {
+fn copy_borrowed_ptr<'a,'b,T>(x: &'a mut &'b mut T) -> &'b mut T {
&mut **p // ERROR due to clause (1)
}
fn main() {
rustc_privacy::provide(&mut local_providers);
typeck::provide(&mut local_providers);
ty::provide(&mut local_providers);
+ reachable::provide(&mut local_providers);
let mut extern_providers = ty::maps::Providers::default();
cstore::provide(&mut extern_providers);