Skip to content

Commit c7f15aa

Browse files
committed
incorporate resolve results into hashing
We now incorporate the `def_map` and `trait_map` results into the SVH.
1 parent 953d711 commit c7f15aa

File tree

10 files changed

+250
-14
lines changed

10 files changed

+250
-14
lines changed

src/librustc/ty/context.rs

+11
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use dep_graph::{DepGraph, DepTrackingMap};
1414
use session::Session;
1515
use middle;
1616
use middle::cstore::LOCAL_CRATE;
17+
use hir::TraitMap;
1718
use hir::def::DefMap;
1819
use hir::def_id::{DefId, DefIndex};
1920
use hir::map as ast_map;
@@ -299,8 +300,16 @@ pub struct GlobalCtxt<'tcx> {
299300
pub types: CommonTypes<'tcx>,
300301

301302
pub sess: &'tcx Session,
303+
304+
/// Map from path id to the results from resolve; generated
305+
/// initially by resolve and updated during typeck in some cases
306+
/// (e.g., UFCS paths)
302307
pub def_map: RefCell<DefMap>,
303308

309+
/// Map indicating what traits are in scope for places where this
310+
/// is relevant; generated by resolve.
311+
pub trait_map: TraitMap,
312+
304313
pub named_region_map: resolve_lifetime::NamedRegionMap,
305314

306315
pub region_maps: RegionMaps,
@@ -666,6 +675,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
666675
pub fn create_and_enter<F, R>(s: &'tcx Session,
667676
arenas: &'tcx CtxtArenas<'tcx>,
668677
def_map: DefMap,
678+
trait_map: TraitMap,
669679
named_region_map: resolve_lifetime::NamedRegionMap,
670680
map: ast_map::Map<'tcx>,
671681
freevars: FreevarMap,
@@ -694,6 +704,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
694704
variance_computed: Cell::new(false),
695705
sess: s,
696706
def_map: RefCell::new(def_map),
707+
trait_map: trait_map,
697708
tables: RefCell::new(Tables::empty()),
698709
impl_trait_refs: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
699710
trait_defs: RefCell::new(DepTrackingMap::new(dep_graph.clone())),

src/librustc_driver/driver.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -846,10 +846,10 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
846846

847847
let index = stability::Index::new(&hir_map);
848848

849-
let trait_map = resolutions.trait_map;
850849
TyCtxt::create_and_enter(sess,
851850
arenas,
852851
resolutions.def_map,
852+
resolutions.trait_map,
853853
named_region_map,
854854
hir_map,
855855
resolutions.freevars,
@@ -864,7 +864,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
864864
|| rustc_incremental::load_dep_graph(tcx));
865865

866866
// passes are timed inside typeck
867-
try_with_f!(typeck::check_crate(tcx, trait_map), (tcx, None, analysis));
867+
try_with_f!(typeck::check_crate(tcx), (tcx, None, analysis));
868868

869869
time(time_passes,
870870
"const checking",

src/librustc_driver/test.rs

+1
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ fn test_env<F>(source_string: &str,
131131
TyCtxt::create_and_enter(&sess,
132132
&arenas,
133133
resolutions.def_map,
134+
resolutions.trait_map,
134135
named_region_map.unwrap(),
135136
ast_map,
136137
resolutions.freevars,

src/librustc_incremental/calculate_svh/svh_visitor.rs

+95-2
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,14 @@ use self::SawAbiComponent::*;
1919
use syntax::ast::{self, Name, NodeId};
2020
use syntax::parse::token;
2121
use syntax_pos::Span;
22-
use rustc::ty::TyCtxt;
2322
use rustc::hir;
2423
use rustc::hir::*;
25-
use rustc::hir::map::DefPath;
24+
use rustc::hir::def::{Def, PathResolution};
25+
use rustc::hir::def_id::DefId;
2626
use rustc::hir::intravisit as visit;
2727
use rustc::hir::intravisit::{Visitor, FnKind};
28+
use rustc::hir::map::DefPath;
29+
use rustc::ty::TyCtxt;
2830

2931
use std::hash::{Hash, SipHasher};
3032

@@ -343,4 +345,95 @@ impl<'a, 'tcx> Visitor<'a> for StrictVersionHashVisitor<'a, 'tcx> {
343345
debug!("visit_arm: st={:?}", self.st);
344346
SawArm.hash(self.st); visit::walk_arm(self, a)
345347
}
348+
349+
fn visit_id(&mut self, id: NodeId) {
350+
debug!("visit_id: id={} st={:?}", id, self.st);
351+
self.hash_resolve(id);
352+
}
353+
}
354+
355+
#[derive(Hash)]
356+
pub enum DefHash {
357+
SawDefId,
358+
SawLabel,
359+
SawPrimTy,
360+
SawSelfTy,
361+
SawErr,
362+
}
363+
364+
impl<'a, 'tcx> StrictVersionHashVisitor<'a, 'tcx> {
365+
fn hash_resolve(&mut self, id: ast::NodeId) {
366+
// Because whether or not a given id has an entry is dependent
367+
// solely on expr variant etc, we don't need to hash whether
368+
// or not an entry was present (we are already hashing what
369+
// variant it is above when we visit the HIR).
370+
371+
if let Some(def) = self.tcx.def_map.borrow().get(&id) {
372+
self.hash_partial_def(def);
373+
}
374+
375+
if let Some(traits) = self.tcx.trait_map.get(&id) {
376+
traits.len().hash(self.st);
377+
for candidate in traits {
378+
self.hash_def_id(candidate.def_id);
379+
}
380+
}
381+
}
382+
383+
fn hash_def_id(&mut self, def_id: DefId) {
384+
let def_path = self.tcx.def_path(def_id);
385+
self.hash_def_path(&def_path);
386+
}
387+
388+
fn hash_partial_def(&mut self, def: &PathResolution) {
389+
self.hash_def(def.base_def);
390+
def.depth.hash(self.st);
391+
}
392+
393+
fn hash_def(&mut self, def: Def) {
394+
match def {
395+
// Crucial point: for all of these variants, the variant +
396+
// add'l data that is added is always the same if the
397+
// def-id is the same, so it suffices to hash the def-id
398+
Def::Fn(..) |
399+
Def::Mod(..) |
400+
Def::ForeignMod(..) |
401+
Def::Static(..) |
402+
Def::Variant(..) |
403+
Def::Enum(..) |
404+
Def::TyAlias(..) |
405+
Def::AssociatedTy(..) |
406+
Def::TyParam(..) |
407+
Def::Struct(..) |
408+
Def::Trait(..) |
409+
Def::Method(..) |
410+
Def::Const(..) |
411+
Def::AssociatedConst(..) |
412+
Def::Local(..) |
413+
Def::Upvar(..) => {
414+
DefHash::SawDefId.hash(self.st);
415+
self.hash_def_id(def.def_id());
416+
}
417+
418+
Def::Label(..) => {
419+
DefHash::SawLabel.hash(self.st);
420+
// we don't encode the `id` because it always refers to something
421+
// within this item, so if it changed, there would have to be other
422+
// changes too
423+
}
424+
Def::PrimTy(ref prim_ty) => {
425+
DefHash::SawPrimTy.hash(self.st);
426+
prim_ty.hash(self.st);
427+
}
428+
Def::SelfTy(..) => {
429+
DefHash::SawSelfTy.hash(self.st);
430+
// the meaning of Self is always the same within a
431+
// given context, so we don't need to hash the other
432+
// fields
433+
}
434+
Def::Err => {
435+
DefHash::SawErr.hash(self.st);
436+
}
437+
}
438+
}
346439
}

src/librustc_incremental/persist/load.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ fn load_dep_graph_if_exists<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
6161
};
6262

6363
match decode_dep_graph(tcx, &dep_graph_data, &work_products_data) {
64-
Ok(()) => return,
64+
Ok(dirty_nodes) => dirty_nodes,
6565
Err(err) => {
6666
tcx.sess.warn(
6767
&format!("decoding error in dep-graph from `{}` and `{}`: {}",

src/librustc_typeck/check/method/probe.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -580,7 +580,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
580580
-> Result<(), MethodError<'tcx>>
581581
{
582582
let mut duplicates = HashSet::new();
583-
let opt_applicable_traits = self.ccx.trait_map.get(&expr_id);
583+
let opt_applicable_traits = self.tcx.trait_map.get(&expr_id);
584584
if let Some(applicable_traits) = opt_applicable_traits {
585585
for trait_candidate in applicable_traits {
586586
let trait_did = trait_candidate.def_id;

src/librustc_typeck/lib.rs

+1-6
Original file line numberDiff line numberDiff line change
@@ -139,9 +139,6 @@ pub struct TypeAndSubsts<'tcx> {
139139
pub struct CrateCtxt<'a, 'tcx: 'a> {
140140
ast_ty_to_ty_cache: RefCell<NodeMap<Ty<'tcx>>>,
141141

142-
/// A mapping from method call sites to traits that have that method.
143-
pub trait_map: hir::TraitMap,
144-
145142
/// A vector of every trait accessible in the whole crate
146143
/// (i.e. including those from subcrates). This is used only for
147144
/// error reporting, and so is lazily initialised and generally
@@ -321,13 +318,11 @@ fn check_for_entry_fn(ccx: &CrateCtxt) {
321318
}
322319
}
323320

324-
pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
325-
trait_map: hir::TraitMap)
321+
pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
326322
-> CompileResult {
327323
let time_passes = tcx.sess.time_passes();
328324
let ccx = CrateCtxt {
329325
ast_ty_to_ty_cache: RefCell::new(NodeMap()),
330-
trait_map: trait_map,
331326
all_traits: RefCell::new(None),
332327
stack: RefCell::new(Vec::new()),
333328
tcx: tcx
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Check that the hash for a method call is sensitive to the traits in
12+
// scope.
13+
14+
// revisions: rpass1 rpass2
15+
16+
#![feature(rustc_attrs)]
17+
18+
fn test<T>() { }
19+
20+
trait Trait1 {
21+
fn method(&self) { }
22+
}
23+
24+
impl Trait1 for () { }
25+
26+
trait Trait2 {
27+
fn method(&self) { }
28+
}
29+
30+
impl Trait2 for () { }
31+
32+
#[cfg(rpass1)]
33+
mod mod3 {
34+
use Trait1;
35+
36+
fn bar() {
37+
().method();
38+
}
39+
40+
fn baz() {
41+
22; // no method call, traits in scope don't matter
42+
}
43+
}
44+
45+
#[cfg(rpass2)]
46+
mod mod3 {
47+
use Trait2;
48+
49+
#[rustc_dirty(label="Hir", cfg="rpass2")]
50+
fn bar() {
51+
().method();
52+
}
53+
54+
#[rustc_clean(label="Hir", cfg="rpass2")]
55+
fn baz() {
56+
22; // no method call, traits in scope don't matter
57+
}
58+
}
59+
60+
fn main() { }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Check that the hash for `mod3::bar` changes when we change the
12+
// `use` to something different.
13+
14+
// revisions: rpass1 rpass2 rpass3
15+
16+
#![feature(rustc_attrs)]
17+
18+
fn test<T>() { }
19+
20+
mod mod1 {
21+
pub struct Foo(pub u32);
22+
}
23+
24+
mod mod2 {
25+
pub struct Foo(pub i64);
26+
}
27+
28+
#[cfg(rpass1)]
29+
mod mod3 {
30+
use test;
31+
use mod1::Foo;
32+
33+
fn in_expr() {
34+
Foo(0);
35+
}
36+
37+
fn in_type() {
38+
test::<Foo>();
39+
}
40+
}
41+
42+
#[cfg(rpass2)]
43+
mod mod3 {
44+
use mod1::Foo; // <-- Nothing changed, but reordered!
45+
use test;
46+
47+
#[rustc_clean(label="Hir", cfg="rpass2")]
48+
fn in_expr() {
49+
Foo(0);
50+
}
51+
52+
#[rustc_clean(label="Hir", cfg="rpass2")]
53+
fn in_type() {
54+
test::<Foo>();
55+
}
56+
}
57+
58+
#[cfg(rpass3)]
59+
mod mod3 {
60+
use test;
61+
use mod2::Foo; // <-- This changed!
62+
63+
#[rustc_dirty(label="Hir", cfg="rpass3")]
64+
fn in_expr() {
65+
Foo(0);
66+
}
67+
68+
#[rustc_dirty(label="Hir", cfg="rpass3")]
69+
fn in_type() {
70+
test::<Foo>();
71+
}
72+
}
73+
74+
fn main() { }

src/test/incremental/string_constant.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,10 @@ mod x {
4141
mod y {
4242
use x;
4343

44-
#[rustc_clean(label="TypeckItemBody", cfg="rpass2")]
45-
#[rustc_clean(label="TransCrateItem", cfg="rpass2")]
44+
// FIXME(#35078) -- when body of `x` changes, we treat it as
45+
// though signature changed.
46+
#[rustc_dirty(label="TypeckItemBody", cfg="rpass2")]
47+
#[rustc_dirty(label="TransCrateItem", cfg="rpass2")]
4648
pub fn y() {
4749
x::x();
4850
}

0 commit comments

Comments
 (0)