]> git.lizzy.rs Git - rust.git/commitdiff
don't index trait impls if the trait isn't also documented
authorQuietMisdreavus <grey@quietmisdreavus.net>
Tue, 28 Aug 2018 16:33:45 +0000 (11:33 -0500)
committerQuietMisdreavus <grey@quietmisdreavus.net>
Thu, 20 Sep 2018 10:42:36 +0000 (05:42 -0500)
src/librustdoc/html/render.rs
src/librustdoc/lib.rs
src/test/rustdoc/traits-in-bodies-private.rs [new file with mode: 0644]

index 22fcbf1728d8da315170977775900fef5088b6b3..ac3dffa3511ae16de86ac198ee32f67367d1b30d 100644 (file)
@@ -337,6 +337,15 @@ pub struct Cache {
     // and their parent id here and indexes them at the end of crate parsing.
     orphan_impl_items: Vec<(DefId, clean::Item)>,
 
+    // Similarly to `orphan_impl_items`, sometimes trait impls are picked up
+    // even though the trait itself is not exported. This can happen if a trait
+    // was defined in function/expression scope, since the impl will be picked
+    // up by `collect-trait-impls` but the trait won't be scraped out in the HIR
+    // crawl. In order to prevent crashes when looking for spotlight traits or
+    // when gathering trait documentation on a type, hold impls here while
+    // folding and add them to the cache later on if we find the trait.
+    orphan_trait_impls: Vec<(DefId, FxHashSet<DefId>, Impl)>,
+
     /// Aliases added through `#[doc(alias = "...")]`. Since a few items can have the same alias,
     /// we need the alias element to have an array of items.
     aliases: FxHashMap<String, Vec<IndexItem>>,
@@ -594,6 +603,7 @@ pub fn run(mut krate: clean::Crate,
         access_levels: krate.access_levels.clone(),
         crate_version: krate.version.take(),
         orphan_impl_items: Vec::new(),
+        orphan_trait_impls: Vec::new(),
         traits: mem::replace(&mut krate.external_traits, FxHashMap()),
         deref_trait_did,
         deref_mut_trait_did,
@@ -636,6 +646,14 @@ pub fn run(mut krate: clean::Crate,
     cache.stack.push(krate.name.clone());
     krate = cache.fold_crate(krate);
 
+    for (trait_did, dids, impl_) in cache.orphan_trait_impls.drain(..) {
+        if cache.traits.contains_key(&trait_did) {
+            for did in dids {
+                cache.impls.entry(did).or_insert(vec![]).push(impl_.clone());
+            }
+        }
+    }
+
     // Build our search index
     let index = build_index(&krate, &mut cache);
 
@@ -1224,7 +1242,7 @@ fn emit_source(&mut self, filename: &FileName) -> io::Result<()> {
 impl DocFolder for Cache {
     fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
         if item.def_id.is_local() {
-            debug!("folding item \"{:?}\", a {}", item.name, item.type_());
+            debug!("folding {} \"{:?}\", id {:?}", item.type_(), item.name, item.def_id);
         }
 
         // If this is a stripped module,
@@ -1457,10 +1475,16 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
                 } else {
                     unreachable!()
                 };
-                for did in dids {
-                    self.impls.entry(did).or_default().push(Impl {
-                        impl_item: item.clone(),
-                    });
+                let impl_item = Impl {
+                    impl_item: item,
+                };
+                if impl_item.trait_did().map_or(true, |d| self.traits.contains_key(&d)) {
+                    for did in dids {
+                        self.impls.entry(did).or_insert(vec![]).push(impl_item.clone());
+                    }
+                } else {
+                    let trait_did = impl_item.trait_did().unwrap();
+                    self.orphan_trait_impls.push((trait_did, dids, impl_item));
                 }
                 None
             } else {
index 5f373a635dd7a671a53402b4c5e677218a22e176..e7bf7fdf3f651ae8d5cd882fda5a7af836c69fb7 100644 (file)
@@ -24,6 +24,7 @@
 #![feature(ptr_offset_from)]
 #![feature(crate_visibility_modifier)]
 #![feature(const_fn)]
+#![feature(drain_filter)]
 
 #![recursion_limit="256"]
 
diff --git a/src/test/rustdoc/traits-in-bodies-private.rs b/src/test/rustdoc/traits-in-bodies-private.rs
new file mode 100644 (file)
index 0000000..ac3be7e
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2018 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.
+
+// when implementing the fix for traits-in-bodies, there was an ICE when documenting private items
+// and a trait was defined in non-module scope
+
+// compile-flags:--document-private-items
+
+// @has traits_in_bodies_private/struct.SomeStruct.html
+// @!has - '//code' 'impl HiddenTrait for SomeStruct'
+pub struct SomeStruct;
+
+fn __implementation_details() {
+    trait HiddenTrait {}
+    impl HiddenTrait for SomeStruct {}
+}