about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMara Bos <m-ou.se@m-ou.se>2020-11-16 17:26:25 +0100
committerGitHub <noreply@github.com>2020-11-16 17:26:25 +0100
commit7a1bd805fa50d1fd3f7a4459038819b748424ab9 (patch)
tree269ab42e5f0b4ae66def66232889bc0d85cb5b03
parentc75f21008de0679d15ee412043dacd14cee0cdb4 (diff)
parentc34350ab4f8a9480dc5fa89d637e61ab7acd5280 (diff)
downloadrust-7a1bd805fa50d1fd3f7a4459038819b748424ab9.tar.gz
rust-7a1bd805fa50d1fd3f7a4459038819b748424ab9.zip
Rollup merge of #78678 - Nemo157:doc-cfg-w-traits, r=jyn514,GuillaumeGomez
Add tests and improve rendering of cfgs on traits

Shows the additional features required to get the trait implementation, suppressing any already shown on the current page. One interesting effect from this is if you have a cfg-ed type, implementing a cfg-ed trait (so the implementation depends on both cfgs), you will get the inverted pair of cfgs shown on each page:

![image](https://user-images.githubusercontent.com/81079/97904671-207bdc00-1d41-11eb-8144-707e8017d2b6.png)

![image](https://user-images.githubusercontent.com/81079/97904700-27a2ea00-1d41-11eb-8b9f-e925ba339044.png)

The hidden items on the trait implementation also now get the correct cfgs displayed on them.

Tests are blocked on #78673.

fixes #68100
cc #43781
-rw-r--r--src/librustdoc/html/render/mod.rs72
-rw-r--r--src/librustdoc/html/static/main.js10
-rw-r--r--src/test/rustdoc/doc-cfg-traits.rs124
3 files changed, 174 insertions, 32 deletions
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index eebb07f0476..fc0ce4b1f09 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -2251,6 +2251,22 @@ fn stability_tags(item: &clean::Item, parent: &clean::Item) -> String {
     tags
 }
 
+fn portability(item: &clean::Item, parent: Option<&clean::Item>) -> Option<String> {
+    let cfg = match (&item.attrs.cfg, parent.and_then(|p| p.attrs.cfg.as_ref())) {
+        (Some(cfg), Some(parent_cfg)) => cfg.simplify_with(parent_cfg),
+        (cfg, _) => cfg.as_deref().cloned(),
+    };
+
+    debug!(
+        "Portability {:?} - {:?} = {:?}",
+        item.attrs.cfg,
+        parent.and_then(|p| p.attrs.cfg.as_ref()),
+        cfg
+    );
+
+    Some(format!("<div class=\"stab portability\">{}</div>", cfg?.render_long_html()))
+}
+
 /// Render the stability and/or deprecation warning that is displayed at the top of the item's
 /// documentation.
 fn short_stability(item: &clean::Item, cx: &Context, parent: Option<&clean::Item>) -> Vec<String> {
@@ -2328,19 +2344,8 @@ fn short_stability(item: &clean::Item, cx: &Context, parent: Option<&clean::Item
         stability.push(format!("<div class=\"stab unstable\">{}</div>", message));
     }
 
-    let cfg = match (&item.attrs.cfg, parent.and_then(|p| p.attrs.cfg.as_ref())) {
-        (Some(cfg), Some(parent_cfg)) => cfg.simplify_with(parent_cfg),
-        (cfg, _) => cfg.as_deref().cloned(),
-    };
-
-    debug!(
-        "Portability {:?} - {:?} = {:?}",
-        item.attrs.cfg,
-        parent.and_then(|p| p.attrs.cfg.as_ref()),
-        cfg
-    );
-    if let Some(cfg) = cfg {
-        stability.push(format!("<div class=\"stab portability\">{}</div>", cfg.render_long_html()));
+    if let Some(portability) = portability(item, parent) {
+        stability.push(portability);
     }
 
     stability
@@ -2431,6 +2436,7 @@ fn item_function(w: &mut Buffer, cx: &Context, it: &clean::Item, f: &clean::Func
 fn render_implementor(
     cx: &Context,
     implementor: &Impl,
+    parent: &clean::Item,
     w: &mut Buffer,
     implementor_dups: &FxHashMap<&str, (DefId, bool)>,
     aliases: &[String],
@@ -2450,7 +2456,7 @@ fn render_implementor(
         w,
         cx,
         implementor,
-        None,
+        parent,
         AssocItemLink::Anchor(None),
         RenderMode::Normal,
         implementor.impl_item.stable_since().as_deref(),
@@ -2480,7 +2486,7 @@ fn render_impls(
                 &mut buffer,
                 cx,
                 i,
-                Some(containing_item),
+                containing_item,
                 assoc_link,
                 RenderMode::Normal,
                 containing_item.stable_since().as_deref(),
@@ -2727,7 +2733,7 @@ fn item_trait(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Trait,
                     w,
                     cx,
                     &implementor,
-                    None,
+                    it,
                     assoc_link,
                     RenderMode::Normal,
                     implementor.impl_item.stable_since().as_deref(),
@@ -2749,7 +2755,7 @@ fn item_trait(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Trait,
             "<div class=\"item-list\" id=\"implementors-list\">",
         );
         for implementor in concrete {
-            render_implementor(cx, implementor, w, &implementor_dups, &[], cache);
+            render_implementor(cx, implementor, it, w, &implementor_dups, &[], cache);
         }
         write_loading_content(w, "</div>");
 
@@ -2764,6 +2770,7 @@ fn item_trait(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Trait,
                 render_implementor(
                     cx,
                     implementor,
+                    it,
                     w,
                     &implementor_dups,
                     &collect_paths_for_type(implementor.inner_impl().for_.clone()),
@@ -3430,7 +3437,7 @@ fn render_assoc_items(
                 w,
                 cx,
                 i,
-                Some(containing_item),
+                containing_item,
                 AssocItemLink::Anchor(None),
                 render_mode,
                 containing_item.stable_since().as_deref(),
@@ -3622,7 +3629,7 @@ fn render_impl(
     w: &mut Buffer,
     cx: &Context,
     i: &Impl,
-    parent: Option<&clean::Item>,
+    parent: &clean::Item,
     link: AssocItemLink<'_>,
     render_mode: RenderMode,
     outer_version: Option<&str>,
@@ -3635,6 +3642,9 @@ fn render_impl(
     aliases: &[String],
     cache: &Cache,
 ) {
+    let traits = &cache.traits;
+    let trait_ = i.trait_did().map(|did| &traits[&did]);
+
     if render_mode == RenderMode::Normal {
         let id = cx.derive_id(match i.inner_impl().trait_ {
             Some(ref t) => {
@@ -3687,6 +3697,13 @@ fn render_impl(
             );
         }
         write!(w, "</h3>");
+
+        if trait_.is_some() {
+            if let Some(portability) = portability(&i.impl_item, Some(parent)) {
+                write!(w, "<div class=\"stability\">{}</div>", portability);
+            }
+        }
+
         if let Some(ref dox) = cx.shared.maybe_collapsed_doc_value(&i.impl_item) {
             let mut ids = cx.id_map.borrow_mut();
             write!(
@@ -3709,7 +3726,7 @@ fn render_impl(
         w: &mut Buffer,
         cx: &Context,
         item: &clean::Item,
-        parent: Option<&clean::Item>,
+        parent: &clean::Item,
         link: AssocItemLink<'_>,
         render_mode: RenderMode,
         is_default_item: bool,
@@ -3794,7 +3811,7 @@ fn render_impl(
                     if let Some(it) = t.items.iter().find(|i| i.name == item.name) {
                         // We need the stability of the item from the trait
                         // because impls can't have a stability.
-                        document_stability(w, cx, it, is_hidden, parent);
+                        document_stability(w, cx, it, is_hidden, Some(parent));
                         if item.doc_value().is_some() {
                             document_full(w, item, cx, "", is_hidden);
                         } else if show_def_docs {
@@ -3804,13 +3821,13 @@ fn render_impl(
                         }
                     }
                 } else {
-                    document_stability(w, cx, item, is_hidden, parent);
+                    document_stability(w, cx, item, is_hidden, Some(parent));
                     if show_def_docs {
                         document_full(w, item, cx, "", is_hidden);
                     }
                 }
             } else {
-                document_stability(w, cx, item, is_hidden, parent);
+                document_stability(w, cx, item, is_hidden, Some(parent));
                 if show_def_docs {
                     document_short(w, item, link, "", is_hidden);
                 }
@@ -3818,16 +3835,13 @@ fn render_impl(
         }
     }
 
-    let traits = &cache.traits;
-    let trait_ = i.trait_did().map(|did| &traits[&did]);
-
     write!(w, "<div class=\"impl-items\">");
     for trait_item in &i.inner_impl().items {
         doc_impl_item(
             w,
             cx,
             trait_item,
-            parent,
+            if trait_.is_some() { &i.impl_item } else { parent },
             link,
             render_mode,
             false,
@@ -3843,7 +3857,7 @@ fn render_impl(
         cx: &Context,
         t: &clean::Trait,
         i: &clean::Impl,
-        parent: Option<&clean::Item>,
+        parent: &clean::Item,
         render_mode: RenderMode,
         outer_version: Option<&str>,
         show_def_docs: bool,
@@ -3884,7 +3898,7 @@ fn render_impl(
                 cx,
                 t,
                 &i.inner_impl(),
-                parent,
+                &i.impl_item,
                 render_mode,
                 outer_version,
                 show_def_docs,
diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js
index cbf15cd0b6e..b8377dc1569 100644
--- a/src/librustdoc/html/static/main.js
+++ b/src/librustdoc/html/static/main.js
@@ -2439,12 +2439,13 @@ function defocusSearchBar() {
 
         var func = function(e) {
             var next = e.nextElementSibling;
+            if (next && hasClass(next, "stability")) {
+              next = next.nextElementSibling;
+            }
             if (!next) {
                 return;
             }
-            if (hasClass(next, "docblock") === true ||
-                (hasClass(next, "stability") === true &&
-                 hasClass(next.nextElementSibling, "docblock") === true)) {
+            if (hasClass(next, "docblock")) {
                 var newToggle = toggle.cloneNode(true);
                 insertAfter(newToggle, e.childNodes[e.childNodes.length - 1]);
                 if (hideMethodDocs === true && hasClass(e, "method") === true) {
@@ -2455,6 +2456,9 @@ function defocusSearchBar() {
 
         var funcImpl = function(e) {
             var next = e.nextElementSibling;
+            if (next && hasClass(next, "stability")) {
+                next = next.nextElementSibling;
+            }
             if (next && hasClass(next, "docblock")) {
                 next = next.nextElementSibling;
             }
diff --git a/src/test/rustdoc/doc-cfg-traits.rs b/src/test/rustdoc/doc-cfg-traits.rs
new file mode 100644
index 00000000000..13407b2c791
--- /dev/null
+++ b/src/test/rustdoc/doc-cfg-traits.rs
@@ -0,0 +1,124 @@
+#![crate_name = "myrmecophagous"]
+#![feature(doc_cfg, associated_type_defaults)]
+
+// @has 'myrmecophagous/index.html'
+// @count   - '//*[@class="stab portability"]' 2
+// @matches - '//*[@class="stab portability"]' '^jurisconsult$'
+// @matches - '//*[@class="stab portability"]' '^quarter$'
+
+pub trait Lea {}
+
+// @has 'myrmecophagous/trait.Vortoscope.html'
+// @count   - '//*[@class="stab portability"]' 6
+// @matches - '//*[@class="stab portability"]' 'crate feature zibib'
+// @matches - '//*[@class="stab portability"]' 'crate feature poriform'
+// @matches - '//*[@class="stab portability"]' 'crate feature ethopoeia'
+// @matches - '//*[@class="stab portability"]' 'crate feature lea'
+// @matches - '//*[@class="stab portability"]' 'crate feature unit'
+// @matches - '//*[@class="stab portability"]' 'crate feature quarter'
+pub trait Vortoscope {
+    type Batology = ();
+
+    #[doc(cfg(feature = "zibib"))]
+    type Zibib = ();
+
+    const YAHRZEIT: () = ();
+
+    #[doc(cfg(feature = "poriform"))]
+    const PORIFORM: () = ();
+
+    fn javanais() {}
+
+    #[doc(cfg(feature = "ethopoeia"))]
+    fn ethopoeia() {}
+}
+
+#[doc(cfg(feature = "lea"))]
+impl<T: Lea> Vortoscope for T {}
+
+#[doc(cfg(feature = "unit"))]
+impl Vortoscope for () {}
+
+// @has 'myrmecophagous/trait.Jurisconsult.html'
+// @count   - '//*[@class="stab portability"]' 7
+// @matches - '//*[@class="stab portability"]' 'crate feature jurisconsult'
+// @matches - '//*[@class="stab portability"]' 'crate feature lithomancy'
+// @matches - '//*[@class="stab portability"]' 'crate feature boodle'
+// @matches - '//*[@class="stab portability"]' 'crate feature mistetch'
+// @matches - '//*[@class="stab portability"]' 'crate feature lea'
+// @matches - '//*[@class="stab portability"]' 'crate feature unit'
+// @matches - '//*[@class="stab portability"]' 'crate feature quarter'
+#[doc(cfg(feature = "jurisconsult"))]
+pub trait Jurisconsult {
+    type Urbanist = ();
+
+    #[doc(cfg(feature = "lithomancy"))]
+    type Lithomancy = ();
+
+    const UNIFILAR: () = ();
+
+    #[doc(cfg(feature = "boodle"))]
+    const BOODLE: () = ();
+
+    fn mersion() {}
+
+    #[doc(cfg(feature = "mistetch"))]
+    fn mistetch() {}
+}
+
+#[doc(cfg(feature = "lea"))]
+impl<T: Lea> Jurisconsult for T {}
+
+#[doc(cfg(feature = "unit"))]
+impl Jurisconsult for () {}
+
+// @has 'myrmecophagous/struct.Ultimogeniture.html'
+// @count   - '//*[@class="stab portability"]' 8
+//
+// @matches - '//*[@class="stab portability"]' 'crate feature zibib'
+// @matches - '//*[@class="stab portability"]' 'crate feature poriform'
+// @matches - '//*[@class="stab portability"]' 'crate feature ethopoeia'
+//
+// @matches - '//*[@class="stab portability"]' 'crate feature jurisconsult'
+// @matches - '//*[@class="stab portability"]' 'crate feature lithomancy'
+// @matches - '//*[@class="stab portability"]' 'crate feature boodle'
+// @matches - '//*[@class="stab portability"]' 'crate feature mistetch'
+//
+// @matches - '//*[@class="stab portability"]' 'crate feature copy'
+#[derive(Clone)]
+pub struct Ultimogeniture;
+
+impl Vortoscope for Ultimogeniture {}
+
+#[doc(cfg(feature = "jurisconsult"))]
+impl Jurisconsult for Ultimogeniture {}
+
+#[doc(cfg(feature = "copy"))]
+impl Copy for Ultimogeniture {}
+
+// @has 'myrmecophagous/struct.Quarter.html'
+// @count   - '//*[@class="stab portability"]' 9
+// @matches - '//*[@class="stab portability"]' 'crate feature quarter'
+//
+// @matches - '//*[@class="stab portability"]' 'crate feature zibib'
+// @matches - '//*[@class="stab portability"]' 'crate feature poriform'
+// @matches - '//*[@class="stab portability"]' 'crate feature ethopoeia'
+//
+// @matches - '//*[@class="stab portability"]' 'crate feature jurisconsult'
+// @matches - '//*[@class="stab portability"]' 'crate feature lithomancy'
+// @matches - '//*[@class="stab portability"]' 'crate feature boodle'
+// @matches - '//*[@class="stab portability"]' 'crate feature mistetch'
+//
+// @matches - '//*[@class="stab portability"]' 'crate feature copy'
+#[doc(cfg(feature = "quarter"))]
+#[derive(Clone)]
+pub struct Quarter;
+
+#[doc(cfg(feature = "quarter"))]
+impl Vortoscope for Quarter {}
+
+#[doc(cfg(all(feature = "jurisconsult", feature = "quarter")))]
+impl Jurisconsult for Quarter {}
+
+#[doc(cfg(all(feature = "copy", feature = "quarter")))]
+impl Copy for Quarter {}