Skip to content

Commit 5415b34

Browse files
committed
write to inherent_impls during the visitor
The goal here is to avoid writing to the `inherent_impls` map from within the general `Coherence` task, and instead write to it as we visit. Writing to it from the Coherence task is actually an information leak; it happened to be safe because Coherence read from `DepNode::Krate`, but that was very coarse. I removed the `Rc` here because, upon manual inspection, nobody clones the data in this table, and it meant that we can accumulate the data in place. That said, the pattern that is used for the inherent impls map is *generally* an anti-pattern (that is, holding the borrow lock for the duration of using the contents), so it'd probably be better to clone (and I doubt that would be expensive -- how many inherent impls does a typical type have?).
1 parent 5114f8a commit 5415b34

File tree

5 files changed

+49
-24
lines changed

5 files changed

+49
-24
lines changed

src/librustc/dep_graph/dep_tracking_map.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,17 @@ impl<M: DepTrackingMapConfig> DepTrackingMap<M> {
8080
pub fn keys(&self) -> Vec<M::Key> {
8181
self.map.keys().cloned().collect()
8282
}
83+
84+
/// Append `elem` to the vector stored for `k`, creating a new vector if needed.
85+
/// This is considered a write to `k`.
86+
pub fn push<E: Clone>(&mut self, k: M::Key, elem: E)
87+
where M: DepTrackingMapConfig<Value=Vec<E>>
88+
{
89+
self.write(&k);
90+
self.map.entry(k)
91+
.or_insert(Vec::new())
92+
.push(elem);
93+
}
8394
}
8495

8596
impl<M: DepTrackingMapConfig> MemoizationMap for RefCell<DepTrackingMap<M>> {

src/librustc/ty/maps.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ dep_map_ty! { ImplTraitRefs: ItemSignature(DefId) -> Option<ty::TraitRef<'tcx>>
3939
dep_map_ty! { TraitDefs: ItemSignature(DefId) -> &'tcx ty::TraitDef<'tcx> }
4040
dep_map_ty! { AdtDefs: ItemSignature(DefId) -> ty::AdtDefMaster<'tcx> }
4141
dep_map_ty! { ItemVariances: ItemSignature(DefId) -> Rc<Vec<ty::Variance>> }
42-
dep_map_ty! { InherentImpls: InherentImpls(DefId) -> Rc<Vec<DefId>> }
42+
dep_map_ty! { InherentImpls: InherentImpls(DefId) -> Vec<DefId> }
4343
dep_map_ty! { ImplItems: ImplItems(DefId) -> Vec<ty::ImplOrTraitItemId> }
4444
dep_map_ty! { TraitItems: TraitItems(DefId) -> Rc<Vec<ty::ImplOrTraitItem<'tcx>>> }
4545
dep_map_ty! { ReprHints: ReprHints(DefId) -> Rc<Vec<attr::ReprAttr>> }

src/librustc/ty/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2665,7 +2665,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
26652665
self.impl_items.borrow_mut().insert(impl_def_id, impl_items);
26662666
}
26672667

2668-
self.inherent_impls.borrow_mut().insert(type_id, Rc::new(inherent_impls));
2668+
self.inherent_impls.borrow_mut().insert(type_id, inherent_impls);
26692669
self.populated_external_types.borrow_mut().insert(type_id);
26702670
}
26712671

src/librustc_typeck/coherence/mod.rs

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,7 @@ use rustc::ty::util::CopyImplementationError;
3232
use middle::free_region::FreeRegionMap;
3333
use CrateCtxt;
3434
use rustc::infer::{self, InferCtxt, TypeOrigin};
35-
use std::cell::RefCell;
36-
use std::rc::Rc;
3735
use syntax_pos::Span;
38-
use util::nodemap::{DefIdMap, FnvHashMap};
3936
use rustc::dep_graph::DepNode;
4037
use rustc::hir::map as hir_map;
4138
use rustc::hir::intravisit;
@@ -49,7 +46,6 @@ mod unsafety;
4946
struct CoherenceChecker<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
5047
crate_context: &'a CrateCtxt<'a, 'gcx>,
5148
inference_context: InferCtxt<'a, 'gcx, 'tcx>,
52-
inherent_impls: RefCell<DefIdMap<Rc<RefCell<Vec<DefId>>>>>,
5349
}
5450

5551
struct CoherenceCheckVisitor<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
@@ -109,15 +105,6 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> {
109105
DepNode::CoherenceCheckImpl,
110106
&mut CoherenceCheckVisitor { cc: self });
111107

112-
// Copy over the inherent impls we gathered up during the walk into
113-
// the tcx.
114-
let mut tcx_inherent_impls =
115-
self.crate_context.tcx.inherent_impls.borrow_mut();
116-
for (k, v) in self.inherent_impls.borrow().iter() {
117-
tcx_inherent_impls.insert((*k).clone(),
118-
Rc::new((*v.borrow()).clone()));
119-
}
120-
121108
// Populate the table of destructors. It might seem a bit strange to
122109
// do this here, but it's actually the most convenient place, since
123110
// the coherence tables contain the trait -> type mappings.
@@ -175,14 +162,8 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> {
175162
}
176163

177164
fn add_inherent_impl(&self, base_def_id: DefId, impl_def_id: DefId) {
178-
if let Some(implementation_list) = self.inherent_impls.borrow().get(&base_def_id) {
179-
implementation_list.borrow_mut().push(impl_def_id);
180-
return;
181-
}
182-
183-
self.inherent_impls.borrow_mut().insert(
184-
base_def_id,
185-
Rc::new(RefCell::new(vec!(impl_def_id))));
165+
let tcx = self.crate_context.tcx;
166+
tcx.inherent_impls.borrow_mut().push(base_def_id, impl_def_id);
186167
}
187168

188169
fn add_trait_impl(&self, impl_trait_ref: ty::TraitRef<'gcx>, impl_def_id: DefId) {
@@ -556,7 +537,6 @@ pub fn check_coherence(ccx: &CrateCtxt) {
556537
CoherenceChecker {
557538
crate_context: ccx,
558539
inference_context: infcx,
559-
inherent_impls: RefCell::new(FnvHashMap()),
560540
}.check();
561541
});
562542
unsafety::check(ccx.tcx);
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
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+
// revisions: rpass1 rpass2
12+
// compile-flags: -Z query-dep-graph
13+
14+
#![allow(warnings)]
15+
#![feature(rustc_attrs)]
16+
#![rustc_partition_reused(module="krate_inherent-x", cfg="rpass2")]
17+
18+
fn main() { }
19+
20+
mod x {
21+
struct Foo;
22+
impl Foo {
23+
fn foo(&self) { }
24+
}
25+
26+
fn method() {
27+
let x: Foo = Foo;
28+
x.foo(); // inherent methods used to add an edge from Krate
29+
}
30+
}
31+
32+
#[cfg(rpass1)]
33+
fn bar() { } // remove this unrelated fn in rpass2, which should not affect `x::method`
34+

0 commit comments

Comments
 (0)