]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #48415 - QuietMisdreavus:traits-on-traits-on-traits, r=Manishearth
authorManish Goregaokar <manishsmail@gmail.com>
Sat, 24 Feb 2018 23:52:11 +0000 (15:52 -0800)
committerGitHub <noreply@github.com>
Sat, 24 Feb 2018 23:52:11 +0000 (15:52 -0800)
rustdoc: don't crash when an external trait's docs needs to import another trait

Fixes https://github.com/rust-lang/rust/issues/48414

When resolving intra-paths for an item, rustdoc needs to have information about their items on hand, for proper bookkeeping. When loading a path for an external item, it needs to load these items from their host crate, since their information isn't otherwise available. This includes resolving paths for those docs. which can cause this process to recurse. Rustdoc keeps a map of external traits in a `RefCell<HashMap<DefId, Trait>>`, and it keeps a borrow of this active when importing an external trait. In the linked crash, this led to a RefCell borrow error, panic, and ICE.

This PR manually releases the borrow while importing the trait, and also keeps a list of traits being imported at the given moment. The latter keeps rustdoc from infinitely recursing as it tries to import the same trait repeatedly.

src/librustdoc/clean/inline.rs
src/librustdoc/core.rs
src/test/rustdoc/auxiliary/issue-48414.rs [new file with mode: 0644]
src/test/rustdoc/issue-48414.rs [new file with mode: 0644]

index d4233309627f5844874b4ab3c66f7b26f53de400..b382ba7f22da713bfa20fb37c662fab4e6461282 100644 (file)
@@ -512,7 +512,16 @@ fn separate_supertrait_bounds(mut g: clean::Generics)
 }
 
 pub fn record_extern_trait(cx: &DocContext, did: DefId) {
-    cx.external_traits.borrow_mut().entry(did).or_insert_with(|| {
-        build_external_trait(cx, did)
-    });
+    if cx.external_traits.borrow().contains_key(&did) ||
+        cx.active_extern_traits.borrow().contains(&did)
+    {
+        return;
+    }
+
+    cx.active_extern_traits.borrow_mut().push(did);
+
+    let trait_ = build_external_trait(cx, did);
+
+    cx.external_traits.borrow_mut().insert(did, trait_);
+    cx.active_extern_traits.borrow_mut().remove_item(&did);
 }
index df7371cdf817b805c6d5e7c2a8f958bd003b26be..9ee0937f425c90cbbb0a88125c16c2cae4ac47ec 100644 (file)
@@ -61,6 +61,9 @@ pub struct DocContext<'a, 'tcx: 'a, 'rcx: 'a> {
     pub renderinfo: RefCell<RenderInfo>,
     /// Later on moved through `clean::Crate` into `html::render::CACHE_KEY`
     pub external_traits: RefCell<FxHashMap<DefId, clean::Trait>>,
+    /// Used while populating `external_traits` to ensure we don't process the same trait twice at
+    /// the same time.
+    pub active_extern_traits: RefCell<Vec<DefId>>,
     // The current set of type and lifetime substitutions,
     // for expanding type aliases at the HIR level:
 
@@ -253,6 +256,7 @@ pub fn run_core(search_paths: SearchPaths,
             populated_all_crate_impls: Cell::new(false),
             access_levels: RefCell::new(access_levels),
             external_traits: Default::default(),
+            active_extern_traits: Default::default(),
             renderinfo: Default::default(),
             ty_substs: Default::default(),
             lt_substs: Default::default(),
diff --git a/src/test/rustdoc/auxiliary/issue-48414.rs b/src/test/rustdoc/auxiliary/issue-48414.rs
new file mode 100644 (file)
index 0000000..7e0edf7
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2015 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.
+
+/// Woah, this trait links to [OtherTrait](OtherTrait)!
+pub trait SomeTrait {}
+
+/// Woah, this trait links to [SomeTrait](SomeTrait)!
+pub trait OtherTrait {}
diff --git a/src/test/rustdoc/issue-48414.rs b/src/test/rustdoc/issue-48414.rs
new file mode 100644 (file)
index 0000000..0136f9c
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2015 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.
+
+// aux-build:issue-48414.rs
+
+// ICE when resolving paths for a trait that linked to another trait, when both were in an external
+// crate
+
+#![crate_name = "base"]
+
+extern crate issue_48414;
+
+#[doc(inline)]
+pub use issue_48414::{SomeTrait, OtherTrait};