Skip to content

Commit 8aba29a

Browse files
shuffle ownership of external_traits
constraints: - clean/inline.rs needs this map to fill in traits when inlining - fold.rs needs this map to allow passes to fold trait items - html/render.rs needs this map to seed the Cache.traits map of all known traits The first two are the real problem, since `DocFolder` only operates on `clean::Crate` but `clean/inline.rs` only sees the `DocContext`. The introduction of early passes means that these two now exist at the same time, so they need to share ownership of the map. Even better, the use of `Crate` in a rustc thread pool means that it needs to be Sync, so it can't use `Lrc<Lock>` to manually activate thread-safety. `parking_lot` is reused from elsewhere in the tree to allow use of its `ReentrantMutex`, as the relevant parts of rustdoc are still single-threaded and this allows for easier use in that context.
1 parent 9e75db4 commit 8aba29a

File tree

9 files changed

+31
-24
lines changed

9 files changed

+31
-24
lines changed

src/Cargo.lock

+1
Original file line numberDiff line numberDiff line change
@@ -2417,6 +2417,7 @@ name = "rustdoc"
24172417
version = "0.0.0"
24182418
dependencies = [
24192419
"minifier 0.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
2420+
"parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
24202421
"pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
24212422
"tempfile 3.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
24222423
]

src/librustdoc/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ path = "lib.rs"
1111
pulldown-cmark = { version = "0.1.2", default-features = false }
1212
minifier = "0.0.19"
1313
tempfile = "3"
14+
parking_lot = "0.6.4"

src/librustdoc/clean/inline.rs

+10-4
Original file line numberDiff line numberDiff line change
@@ -538,17 +538,23 @@ pub fn record_extern_trait(cx: &DocContext, did: DefId) {
538538
return;
539539
}
540540

541-
if cx.external_traits.borrow().contains_key(&did) ||
542-
cx.active_extern_traits.borrow().contains(&did)
543541
{
544-
return;
542+
let external_traits = cx.external_traits.lock();
543+
if external_traits.borrow().contains_key(&did) ||
544+
cx.active_extern_traits.borrow().contains(&did)
545+
{
546+
return;
547+
}
545548
}
546549

547550
cx.active_extern_traits.borrow_mut().push(did);
548551

549552
debug!("record_extern_trait: {:?}", did);
550553
let trait_ = build_external_trait(cx, did);
551554

552-
cx.external_traits.borrow_mut().insert(did, trait_);
555+
{
556+
let external_traits = cx.external_traits.lock();
557+
external_traits.borrow_mut().insert(did, trait_);
558+
}
553559
cx.active_extern_traits.borrow_mut().remove_item(&did);
554560
}

src/librustdoc/clean/mod.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ use std::cell::RefCell;
5555
use std::sync::Arc;
5656
use std::u32;
5757

58+
use parking_lot::ReentrantMutex;
59+
5860
use core::{self, DocContext};
5961
use doctree;
6062
use visit_ast;
@@ -136,7 +138,7 @@ pub struct Crate {
136138
pub primitives: Vec<(DefId, PrimitiveType, Attributes)>,
137139
// These are later on moved into `CACHEKEY`, leaving the map empty.
138140
// Only here so that they can be filtered through the rustdoc passes.
139-
pub external_traits: FxHashMap<DefId, Trait>,
141+
pub external_traits: Arc<ReentrantMutex<RefCell<FxHashMap<DefId, Trait>>>>,
140142
pub masked_crates: FxHashSet<CrateNum>,
141143
}
142144

@@ -214,7 +216,7 @@ impl<'a, 'tcx, 'rcx, 'cstore> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tc
214216
module: Some(module),
215217
externs,
216218
primitives,
217-
external_traits: Default::default(),
219+
external_traits: cx.external_traits.clone(),
218220
masked_crates,
219221
}
220222
}

src/librustdoc/core.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,13 @@ use syntax::symbol::keywords;
3636
use syntax_pos::DUMMY_SP;
3737
use errors;
3838
use errors::emitter::{Emitter, EmitterWriter};
39+
use parking_lot::ReentrantMutex;
3940

4041
use std::cell::RefCell;
4142
use std::mem;
4243
use rustc_data_structures::sync::{self, Lrc};
4344
use std::rc::Rc;
45+
use std::sync::Arc;
4446
use std::path::PathBuf;
4547

4648
use visit_ast::RustdocVisitor;
@@ -66,7 +68,7 @@ pub struct DocContext<'a, 'tcx: 'a, 'rcx: 'a, 'cstore: 'rcx> {
6668
/// Later on moved into `html::render::CACHE_KEY`
6769
pub renderinfo: RefCell<RenderInfo>,
6870
/// Later on moved through `clean::Crate` into `html::render::CACHE_KEY`
69-
pub external_traits: RefCell<FxHashMap<DefId, clean::Trait>>,
71+
pub external_traits: Arc<ReentrantMutex<RefCell<FxHashMap<DefId, clean::Trait>>>>,
7072
/// Used while populating `external_traits` to ensure we don't process the same trait twice at
7173
/// the same time.
7274
pub active_extern_traits: RefCell<Vec<DefId>>,
@@ -596,8 +598,6 @@ pub fn run_core(search_paths: SearchPaths,
596598

597599
ctxt.sess().abort_if_errors();
598600

599-
krate.external_traits = ctxt.external_traits.into_inner();
600-
601601
(krate, ctxt.renderinfo.into_inner(), passes)
602602
}), &sess)
603603
})

src/librustdoc/fold.rs

+8-7
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use std::mem;
12-
1311
use clean::*;
1412

1513
pub struct StripItem(pub Item);
@@ -116,11 +114,14 @@ pub trait DocFolder : Sized {
116114
fn fold_crate(&mut self, mut c: Crate) -> Crate {
117115
c.module = c.module.take().and_then(|module| self.fold_item(module));
118116

119-
let traits = mem::replace(&mut c.external_traits, Default::default());
120-
c.external_traits.extend(traits.into_iter().map(|(k, mut v)| {
121-
v.items = v.items.into_iter().filter_map(|i| self.fold_item(i)).collect();
122-
(k, v)
123-
}));
117+
{
118+
let guard = c.external_traits.lock();
119+
let traits = guard.replace(Default::default());
120+
guard.borrow_mut().extend(traits.into_iter().map(|(k, mut v)| {
121+
v.items = v.items.into_iter().filter_map(|i| self.fold_item(i)).collect();
122+
(k, v)
123+
}));
124+
}
124125
c
125126
}
126127
}

src/librustdoc/html/render.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -606,7 +606,7 @@ pub fn run(mut krate: clean::Crate,
606606
crate_version: krate.version.take(),
607607
orphan_impl_items: Vec::new(),
608608
orphan_trait_impls: Vec::new(),
609-
traits: mem::replace(&mut krate.external_traits, FxHashMap()),
609+
traits: krate.external_traits.lock().replace(FxHashMap()),
610610
deref_trait_did,
611611
deref_mut_trait_did,
612612
owned_box_did,

src/librustdoc/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ extern crate rustc_errors as errors;
5050
extern crate pulldown_cmark;
5151
extern crate tempfile;
5252
extern crate minifier;
53+
extern crate parking_lot;
5354

5455
extern crate serialize as rustc_serialize; // used by deriving
5556

src/librustdoc/passes/strip_hidden.rs

+2-7
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,9 @@ pub const STRIP_HIDDEN: Pass =
2424
"strips all doc(hidden) items from the output");
2525

2626
/// Strip items marked `#[doc(hidden)]`
27-
pub fn strip_hidden(mut krate: clean::Crate, cx: &DocContext) -> clean::Crate {
27+
pub fn strip_hidden(krate: clean::Crate, _: &DocContext) -> clean::Crate {
2828
let mut retained = DefIdSet();
2929

30-
// as an early pass, the external traits haven't been swapped in, so we need to do that ahead
31-
// of time
32-
mem::swap(&mut krate.external_traits, &mut cx.external_traits.borrow_mut());
33-
3430
// strip all #[doc(hidden)] items
3531
let krate = {
3632
let mut stripper = Stripper{ retained: &mut retained, update_retained: true };
@@ -39,8 +35,7 @@ pub fn strip_hidden(mut krate: clean::Crate, cx: &DocContext) -> clean::Crate {
3935

4036
// strip all impls referencing stripped items
4137
let mut stripper = ImplStripper { retained: &retained };
42-
let mut krate = stripper.fold_crate(krate);
43-
mem::swap(&mut krate.external_traits, &mut cx.external_traits.borrow_mut());
38+
let krate = stripper.fold_crate(krate);
4439

4540
krate
4641
}

0 commit comments

Comments
 (0)