diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2016-07-27 17:26:55 -0400 |
|---|---|---|
| committer | Niko Matsakis <niko@alum.mit.edu> | 2016-08-09 20:28:46 -0400 |
| commit | c7f15aa178c179cc664dafa062121d854df5a3f6 (patch) | |
| tree | f90971f8452bcba05fae916ff1bb18769def828a | |
| parent | 953d711cc74457981bc01e0090ba67b9a5779e5b (diff) | |
incorporate resolve results into hashing
We now incorporate the `def_map` and `trait_map` results into the SVH.
| -rw-r--r-- | src/librustc/ty/context.rs | 11 | ||||
| -rw-r--r-- | src/librustc_driver/driver.rs | 4 | ||||
| -rw-r--r-- | src/librustc_driver/test.rs | 1 | ||||
| -rw-r--r-- | src/librustc_incremental/calculate_svh/svh_visitor.rs | 97 | ||||
| -rw-r--r-- | src/librustc_incremental/persist/load.rs | 2 | ||||
| -rw-r--r-- | src/librustc_typeck/check/method/probe.rs | 2 | ||||
| -rw-r--r-- | src/librustc_typeck/lib.rs | 7 | ||||
| -rw-r--r-- | src/test/incremental/ich_method_call_trait_scope.rs | 60 | ||||
| -rw-r--r-- | src/test/incremental/ich_resolve_results.rs | 74 | ||||
| -rw-r--r-- | src/test/incremental/string_constant.rs | 6 |
10 files changed, 250 insertions, 14 deletions
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 77cc62060aa..a816d26edad 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -14,6 +14,7 @@ use dep_graph::{DepGraph, DepTrackingMap}; use session::Session; use middle; use middle::cstore::LOCAL_CRATE; +use hir::TraitMap; use hir::def::DefMap; use hir::def_id::{DefId, DefIndex}; use hir::map as ast_map; @@ -299,8 +300,16 @@ pub struct GlobalCtxt<'tcx> { pub types: CommonTypes<'tcx>, pub sess: &'tcx Session, + + /// Map from path id to the results from resolve; generated + /// initially by resolve and updated during typeck in some cases + /// (e.g., UFCS paths) pub def_map: RefCell<DefMap>, + /// Map indicating what traits are in scope for places where this + /// is relevant; generated by resolve. + pub trait_map: TraitMap, + pub named_region_map: resolve_lifetime::NamedRegionMap, pub region_maps: RegionMaps, @@ -666,6 +675,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn create_and_enter<F, R>(s: &'tcx Session, arenas: &'tcx CtxtArenas<'tcx>, def_map: DefMap, + trait_map: TraitMap, named_region_map: resolve_lifetime::NamedRegionMap, map: ast_map::Map<'tcx>, freevars: FreevarMap, @@ -694,6 +704,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { variance_computed: Cell::new(false), sess: s, def_map: RefCell::new(def_map), + trait_map: trait_map, tables: RefCell::new(Tables::empty()), impl_trait_refs: RefCell::new(DepTrackingMap::new(dep_graph.clone())), trait_defs: RefCell::new(DepTrackingMap::new(dep_graph.clone())), diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index f1f5e194da4..7f50522b203 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -846,10 +846,10 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, let index = stability::Index::new(&hir_map); - let trait_map = resolutions.trait_map; TyCtxt::create_and_enter(sess, arenas, resolutions.def_map, + resolutions.trait_map, named_region_map, hir_map, resolutions.freevars, @@ -864,7 +864,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, || rustc_incremental::load_dep_graph(tcx)); // passes are timed inside typeck - try_with_f!(typeck::check_crate(tcx, trait_map), (tcx, None, analysis)); + try_with_f!(typeck::check_crate(tcx), (tcx, None, analysis)); time(time_passes, "const checking", diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index 39763bfa0eb..2b0bd14d83f 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -131,6 +131,7 @@ fn test_env<F>(source_string: &str, TyCtxt::create_and_enter(&sess, &arenas, resolutions.def_map, + resolutions.trait_map, named_region_map.unwrap(), ast_map, resolutions.freevars, diff --git a/src/librustc_incremental/calculate_svh/svh_visitor.rs b/src/librustc_incremental/calculate_svh/svh_visitor.rs index d15734dce70..42e7abeeaca 100644 --- a/src/librustc_incremental/calculate_svh/svh_visitor.rs +++ b/src/librustc_incremental/calculate_svh/svh_visitor.rs @@ -19,12 +19,14 @@ use self::SawAbiComponent::*; use syntax::ast::{self, Name, NodeId}; use syntax::parse::token; use syntax_pos::Span; -use rustc::ty::TyCtxt; use rustc::hir; use rustc::hir::*; -use rustc::hir::map::DefPath; +use rustc::hir::def::{Def, PathResolution}; +use rustc::hir::def_id::DefId; use rustc::hir::intravisit as visit; use rustc::hir::intravisit::{Visitor, FnKind}; +use rustc::hir::map::DefPath; +use rustc::ty::TyCtxt; use std::hash::{Hash, SipHasher}; @@ -343,4 +345,95 @@ impl<'a, 'tcx> Visitor<'a> for StrictVersionHashVisitor<'a, 'tcx> { debug!("visit_arm: st={:?}", self.st); SawArm.hash(self.st); visit::walk_arm(self, a) } + + fn visit_id(&mut self, id: NodeId) { + debug!("visit_id: id={} st={:?}", id, self.st); + self.hash_resolve(id); + } +} + +#[derive(Hash)] +pub enum DefHash { + SawDefId, + SawLabel, + SawPrimTy, + SawSelfTy, + SawErr, +} + +impl<'a, 'tcx> StrictVersionHashVisitor<'a, 'tcx> { + fn hash_resolve(&mut self, id: ast::NodeId) { + // Because whether or not a given id has an entry is dependent + // solely on expr variant etc, we don't need to hash whether + // or not an entry was present (we are already hashing what + // variant it is above when we visit the HIR). + + if let Some(def) = self.tcx.def_map.borrow().get(&id) { + self.hash_partial_def(def); + } + + if let Some(traits) = self.tcx.trait_map.get(&id) { + traits.len().hash(self.st); + for candidate in traits { + self.hash_def_id(candidate.def_id); + } + } + } + + fn hash_def_id(&mut self, def_id: DefId) { + let def_path = self.tcx.def_path(def_id); + self.hash_def_path(&def_path); + } + + fn hash_partial_def(&mut self, def: &PathResolution) { + self.hash_def(def.base_def); + def.depth.hash(self.st); + } + + fn hash_def(&mut self, def: Def) { + match def { + // Crucial point: for all of these variants, the variant + + // add'l data that is added is always the same if the + // def-id is the same, so it suffices to hash the def-id + Def::Fn(..) | + Def::Mod(..) | + Def::ForeignMod(..) | + Def::Static(..) | + Def::Variant(..) | + Def::Enum(..) | + Def::TyAlias(..) | + Def::AssociatedTy(..) | + Def::TyParam(..) | + Def::Struct(..) | + Def::Trait(..) | + Def::Method(..) | + Def::Const(..) | + Def::AssociatedConst(..) | + Def::Local(..) | + Def::Upvar(..) => { + DefHash::SawDefId.hash(self.st); + self.hash_def_id(def.def_id()); + } + + Def::Label(..) => { + DefHash::SawLabel.hash(self.st); + // we don't encode the `id` because it always refers to something + // within this item, so if it changed, there would have to be other + // changes too + } + Def::PrimTy(ref prim_ty) => { + DefHash::SawPrimTy.hash(self.st); + prim_ty.hash(self.st); + } + Def::SelfTy(..) => { + DefHash::SawSelfTy.hash(self.st); + // the meaning of Self is always the same within a + // given context, so we don't need to hash the other + // fields + } + Def::Err => { + DefHash::SawErr.hash(self.st); + } + } + } } diff --git a/src/librustc_incremental/persist/load.rs b/src/librustc_incremental/persist/load.rs index 48ddcd2c416..79b90b63dc6 100644 --- a/src/librustc_incremental/persist/load.rs +++ b/src/librustc_incremental/persist/load.rs @@ -61,7 +61,7 @@ fn load_dep_graph_if_exists<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { }; match decode_dep_graph(tcx, &dep_graph_data, &work_products_data) { - Ok(()) => return, + Ok(dirty_nodes) => dirty_nodes, Err(err) => { tcx.sess.warn( &format!("decoding error in dep-graph from `{}` and `{}`: {}", diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 6a1baf13b27..648d1f42fb5 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -580,7 +580,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { -> Result<(), MethodError<'tcx>> { let mut duplicates = HashSet::new(); - let opt_applicable_traits = self.ccx.trait_map.get(&expr_id); + let opt_applicable_traits = self.tcx.trait_map.get(&expr_id); if let Some(applicable_traits) = opt_applicable_traits { for trait_candidate in applicable_traits { let trait_did = trait_candidate.def_id; diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 65e00705121..eac26487ea3 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -139,9 +139,6 @@ pub struct TypeAndSubsts<'tcx> { pub struct CrateCtxt<'a, 'tcx: 'a> { ast_ty_to_ty_cache: RefCell<NodeMap<Ty<'tcx>>>, - /// A mapping from method call sites to traits that have that method. - pub trait_map: hir::TraitMap, - /// A vector of every trait accessible in the whole crate /// (i.e. including those from subcrates). This is used only for /// error reporting, and so is lazily initialised and generally @@ -321,13 +318,11 @@ fn check_for_entry_fn(ccx: &CrateCtxt) { } } -pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - trait_map: hir::TraitMap) +pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> CompileResult { let time_passes = tcx.sess.time_passes(); let ccx = CrateCtxt { ast_ty_to_ty_cache: RefCell::new(NodeMap()), - trait_map: trait_map, all_traits: RefCell::new(None), stack: RefCell::new(Vec::new()), tcx: tcx diff --git a/src/test/incremental/ich_method_call_trait_scope.rs b/src/test/incremental/ich_method_call_trait_scope.rs new file mode 100644 index 00000000000..f28ecf74dd4 --- /dev/null +++ b/src/test/incremental/ich_method_call_trait_scope.rs @@ -0,0 +1,60 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <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. + +// Check that the hash for a method call is sensitive to the traits in +// scope. + +// revisions: rpass1 rpass2 + +#![feature(rustc_attrs)] + +fn test<T>() { } + +trait Trait1 { + fn method(&self) { } +} + +impl Trait1 for () { } + +trait Trait2 { + fn method(&self) { } +} + +impl Trait2 for () { } + +#[cfg(rpass1)] +mod mod3 { + use Trait1; + + fn bar() { + ().method(); + } + + fn baz() { + 22; // no method call, traits in scope don't matter + } +} + +#[cfg(rpass2)] +mod mod3 { + use Trait2; + + #[rustc_dirty(label="Hir", cfg="rpass2")] + fn bar() { + ().method(); + } + + #[rustc_clean(label="Hir", cfg="rpass2")] + fn baz() { + 22; // no method call, traits in scope don't matter + } +} + +fn main() { } diff --git a/src/test/incremental/ich_resolve_results.rs b/src/test/incremental/ich_resolve_results.rs new file mode 100644 index 00000000000..680a91da09f --- /dev/null +++ b/src/test/incremental/ich_resolve_results.rs @@ -0,0 +1,74 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <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. + +// Check that the hash for `mod3::bar` changes when we change the +// `use` to something different. + +// revisions: rpass1 rpass2 rpass3 + +#![feature(rustc_attrs)] + +fn test<T>() { } + +mod mod1 { + pub struct Foo(pub u32); +} + +mod mod2 { + pub struct Foo(pub i64); +} + +#[cfg(rpass1)] +mod mod3 { + use test; + use mod1::Foo; + + fn in_expr() { + Foo(0); + } + + fn in_type() { + test::<Foo>(); + } +} + +#[cfg(rpass2)] +mod mod3 { + use mod1::Foo; // <-- Nothing changed, but reordered! + use test; + + #[rustc_clean(label="Hir", cfg="rpass2")] + fn in_expr() { + Foo(0); + } + + #[rustc_clean(label="Hir", cfg="rpass2")] + fn in_type() { + test::<Foo>(); + } +} + +#[cfg(rpass3)] +mod mod3 { + use test; + use mod2::Foo; // <-- This changed! + + #[rustc_dirty(label="Hir", cfg="rpass3")] + fn in_expr() { + Foo(0); + } + + #[rustc_dirty(label="Hir", cfg="rpass3")] + fn in_type() { + test::<Foo>(); + } +} + +fn main() { } diff --git a/src/test/incremental/string_constant.rs b/src/test/incremental/string_constant.rs index f4062169256..72072248ec0 100644 --- a/src/test/incremental/string_constant.rs +++ b/src/test/incremental/string_constant.rs @@ -41,8 +41,10 @@ mod x { mod y { use x; - #[rustc_clean(label="TypeckItemBody", cfg="rpass2")] - #[rustc_clean(label="TransCrateItem", cfg="rpass2")] + // FIXME(#35078) -- when body of `x` changes, we treat it as + // though signature changed. + #[rustc_dirty(label="TypeckItemBody", cfg="rpass2")] + #[rustc_dirty(label="TransCrateItem", cfg="rpass2")] pub fn y() { x::x(); } |
