mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-23 15:23:46 +00:00
incorporate resolve results into hashing
We now incorporate the `def_map` and `trait_map` results into the SVH.
This commit is contained in:
parent
953d711cc7
commit
c7f15aa178
@ -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())),
|
||||
|
@ -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",
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 `{}`: {}",
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
60
src/test/incremental/ich_method_call_trait_scope.rs
Normal file
60
src/test/incremental/ich_method_call_trait_scope.rs
Normal file
@ -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() { }
|
74
src/test/incremental/ich_resolve_results.rs
Normal file
74
src/test/incremental/ich_resolve_results.rs
Normal file
@ -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() { }
|
@ -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();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user