Skip to content

Commit 1cff03d

Browse files
committed
Revert "Remove "important traits" feature"
This reverts commit 1244ced.
1 parent 0c03aee commit 1cff03d

File tree

15 files changed

+392
-8
lines changed

15 files changed

+392
-8
lines changed

src/doc/rustdoc/src/unstable-features.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,27 @@ Book][unstable-doc-cfg] and [its tracking issue][issue-doc-cfg].
138138
[unstable-doc-cfg]: ../unstable-book/language-features/doc-cfg.html
139139
[issue-doc-cfg]: https://github.com/rust-lang/rust/issues/43781
140140

141+
### Adding your trait to the "Important Traits" dialog
142+
143+
Rustdoc keeps a list of a few traits that are believed to be "fundamental" to a given type when
144+
implemented on it. These traits are intended to be the primary interface for their types, and are
145+
often the only thing available to be documented on their types. For this reason, Rustdoc will track
146+
when a given type implements one of these traits and call special attention to it when a function
147+
returns one of these types. This is the "Important Traits" dialog, visible as a circle-i button next
148+
to the function, which, when clicked, shows the dialog.
149+
150+
In the standard library, the traits that qualify for inclusion are `Iterator`, `io::Read`, and
151+
`io::Write`. However, rather than being implemented as a hard-coded list, these traits have a
152+
special marker attribute on them: `#[doc(spotlight)]`. This means that you could apply this
153+
attribute to your own trait to include it in the "Important Traits" dialog in documentation.
154+
155+
The `#[doc(spotlight)]` attribute currently requires the `#![feature(doc_spotlight)]` feature gate.
156+
For more information, see [its chapter in the Unstable Book][unstable-spotlight] and [its tracking
157+
issue][issue-spotlight].
158+
159+
[unstable-spotlight]: ../unstable-book/language-features/doc-spotlight.html
160+
[issue-spotlight]: https://github.com/rust-lang/rust/issues/45040
161+
141162
### Exclude certain dependencies from documentation
142163

143164
The standard library uses several dependencies which, in turn, use several types and traits from the
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# `doc_spotlight`
2+
3+
The tracking issue for this feature is: [#45040]
4+
5+
The `doc_spotlight` feature allows the use of the `spotlight` parameter to the `#[doc]` attribute,
6+
to "spotlight" a specific trait on the return values of functions. Adding a `#[doc(spotlight)]`
7+
attribute to a trait definition will make rustdoc print extra information for functions which return
8+
a type that implements that trait. This attribute is applied to the `Iterator`, `io::Read`, and
9+
`io::Write` traits in the standard library.
10+
11+
You can do this on your own traits, like this:
12+
13+
```
14+
#![feature(doc_spotlight)]
15+
16+
#[doc(spotlight)]
17+
pub trait MyTrait {}
18+
19+
pub struct MyStruct;
20+
impl MyTrait for MyStruct {}
21+
22+
/// The docs for this function will have an extra line about `MyStruct` implementing `MyTrait`,
23+
/// without having to write that yourself!
24+
pub fn my_fn() -> MyStruct { MyStruct }
25+
```
26+
27+
This feature was originally implemented in PR [#45039].
28+
29+
[#45040]: https://github.com/rust-lang/rust/issues/45040
30+
[#45039]: https://github.com/rust-lang/rust/pull/45039

src/librustc_feature/active.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,9 @@ declare_features! (
368368
/// Allows `#[doc(masked)]`.
369369
(active, doc_masked, "1.21.0", Some(44027), None),
370370

371+
/// Allows `#[doc(spotlight)]`.
372+
(active, doc_spotlight, "1.22.0", Some(45040), None),
373+
371374
/// Allows `#[doc(include = "some-file")]`.
372375
(active, external_doc, "1.22.0", Some(44732), None),
373376

src/librustdoc/clean/inline.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use rustc_metadata::creader::LoadedMacro;
1212
use rustc_middle::ty;
1313
use rustc_mir::const_eval::is_min_const_fn;
1414
use rustc_span::hygiene::MacroKind;
15-
use rustc_span::symbol::Symbol;
15+
use rustc_span::symbol::{sym, Symbol};
1616
use rustc_span::Span;
1717

1818
use crate::clean::{self, GetDefId, ToSource, TypeKind};
@@ -194,13 +194,15 @@ pub fn build_external_trait(cx: &DocContext<'_>, did: DefId) -> clean::Trait {
194194
let generics = (cx.tcx.generics_of(did), predicates).clean(cx);
195195
let generics = filter_non_trait_generics(did, generics);
196196
let (generics, supertrait_bounds) = separate_supertrait_bounds(generics);
197+
let is_spotlight = load_attrs(cx, did).clean(cx).has_doc_flag(sym::spotlight);
197198
let is_auto = cx.tcx.trait_is_auto(did);
198199
clean::Trait {
199200
auto: auto_trait,
200201
unsafety: cx.tcx.trait_def(did).unsafety,
201202
generics,
202203
items: trait_items,
203204
bounds: supertrait_bounds,
205+
is_spotlight,
204206
is_auto,
205207
}
206208
}

src/librustdoc/clean/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,6 +1007,7 @@ impl Clean<FnRetTy> for hir::FnRetTy<'_> {
10071007
impl Clean<Item> for doctree::Trait<'_> {
10081008
fn clean(&self, cx: &DocContext<'_>) -> Item {
10091009
let attrs = self.attrs.clean(cx);
1010+
let is_spotlight = attrs.has_doc_flag(sym::spotlight);
10101011
Item {
10111012
name: Some(self.name.clean(cx)),
10121013
attrs,
@@ -1021,6 +1022,7 @@ impl Clean<Item> for doctree::Trait<'_> {
10211022
items: self.items.iter().map(|ti| ti.clean(cx)).collect(),
10221023
generics: self.generics.clean(cx),
10231024
bounds: self.bounds.clean(cx),
1025+
is_spotlight,
10241026
is_auto: self.is_auto.clean(cx),
10251027
}),
10261028
}

src/librustdoc/clean/types.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -993,6 +993,7 @@ pub struct Trait {
993993
pub items: Vec<Item>,
994994
pub generics: Generics,
995995
pub bounds: Vec<GenericBound>,
996+
pub is_spotlight: bool,
996997
pub is_auto: bool,
997998
}
998999

src/librustdoc/html/format.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,22 @@ impl Buffer {
6363
Buffer { for_html: false, buffer: String::new() }
6464
}
6565

66+
crate fn is_empty(&self) -> bool {
67+
self.buffer.is_empty()
68+
}
69+
6670
crate fn into_inner(self) -> String {
6771
self.buffer
6872
}
6973

74+
crate fn insert_str(&mut self, idx: usize, s: &str) {
75+
self.buffer.insert_str(idx, s);
76+
}
77+
78+
crate fn push_str(&mut self, s: &str) {
79+
self.buffer.push_str(s);
80+
}
81+
7082
// Intended for consumption by write! and writeln! (std::fmt) but without
7183
// the fmt::Result return type imposed by fmt::Write (and avoiding the trait
7284
// import).

src/librustdoc/html/render.rs

Lines changed: 81 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2384,7 +2384,7 @@ fn item_function(w: &mut Buffer, cx: &Context, it: &clean::Item, f: &clean::Func
23842384
f.generics.print()
23852385
)
23862386
.len();
2387-
write!(w, "<pre class='rust fn'>");
2387+
write!(w, "{}<pre class='rust fn'>", render_spotlight_traits(it));
23882388
render_attributes(w, it, false);
23892389
write!(
23902390
w,
@@ -2587,7 +2587,13 @@ fn item_trait(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Trait)
25872587
let item_type = m.type_();
25882588
let id = cx.derive_id(format!("{}.{}", item_type, name));
25892589
let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space()));
2590-
write!(w, "<h3 id='{id}' class='method'><code id='{ns_id}'>", id = id, ns_id = ns_id);
2590+
write!(
2591+
w,
2592+
"<h3 id='{id}' class='method'>{extra}<code id='{ns_id}'>",
2593+
extra = render_spotlight_traits(m),
2594+
id = id,
2595+
ns_id = ns_id
2596+
);
25912597
render_assoc_item(w, m, AssocItemLink::Anchor(Some(&id)), ItemType::Impl);
25922598
write!(w, "</code>");
25932599
render_stability_since(w, m, t);
@@ -3550,6 +3556,76 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool) -> bool {
35503556
}
35513557
}
35523558

3559+
fn render_spotlight_traits(item: &clean::Item) -> String {
3560+
match item.inner {
3561+
clean::FunctionItem(clean::Function { ref decl, .. })
3562+
| clean::TyMethodItem(clean::TyMethod { ref decl, .. })
3563+
| clean::MethodItem(clean::Method { ref decl, .. })
3564+
| clean::ForeignFunctionItem(clean::Function { ref decl, .. }) => spotlight_decl(decl),
3565+
_ => String::new(),
3566+
}
3567+
}
3568+
3569+
fn spotlight_decl(decl: &clean::FnDecl) -> String {
3570+
let mut out = Buffer::html();
3571+
let mut trait_ = String::new();
3572+
3573+
if let Some(did) = decl.output.def_id() {
3574+
let c = cache();
3575+
if let Some(impls) = c.impls.get(&did) {
3576+
for i in impls {
3577+
let impl_ = i.inner_impl();
3578+
if impl_.trait_.def_id().map_or(false, |d| c.traits[&d].is_spotlight) {
3579+
if out.is_empty() {
3580+
out.push_str(&format!(
3581+
"<h3 class=\"important\">Important traits for {}</h3>\
3582+
<code class=\"content\">",
3583+
impl_.for_.print()
3584+
));
3585+
trait_.push_str(&impl_.for_.print().to_string());
3586+
}
3587+
3588+
//use the "where" class here to make it small
3589+
out.push_str(&format!(
3590+
"<span class=\"where fmt-newline\">{}</span>",
3591+
impl_.print()
3592+
));
3593+
let t_did = impl_.trait_.def_id().unwrap();
3594+
for it in &impl_.items {
3595+
if let clean::TypedefItem(ref tydef, _) = it.inner {
3596+
out.push_str("<span class=\"where fmt-newline\"> ");
3597+
assoc_type(
3598+
&mut out,
3599+
it,
3600+
&[],
3601+
Some(&tydef.type_),
3602+
AssocItemLink::GotoSource(t_did, &FxHashSet::default()),
3603+
"",
3604+
);
3605+
out.push_str(";</span>");
3606+
}
3607+
}
3608+
}
3609+
}
3610+
}
3611+
}
3612+
3613+
if !out.is_empty() {
3614+
out.insert_str(
3615+
0,
3616+
&format!(
3617+
"<div class=\"important-traits\"><div class='tooltip'>ⓘ\
3618+
<span class='tooltiptext'>Important traits for {}</span></div>\
3619+
<div class=\"content hidden\">",
3620+
trait_
3621+
),
3622+
);
3623+
out.push_str("</code></div></div>");
3624+
}
3625+
3626+
out.into_inner()
3627+
}
3628+
35533629
fn render_impl(
35543630
w: &mut Buffer,
35553631
cx: &Context,
@@ -3656,13 +3732,14 @@ fn render_impl(
36563732
(true, " hidden")
36573733
};
36583734
match item.inner {
3659-
clean::MethodItem(clean::Method { .. })
3660-
| clean::TyMethodItem(clean::TyMethod { .. }) => {
3735+
clean::MethodItem(clean::Method { ref decl, .. })
3736+
| clean::TyMethodItem(clean::TyMethod { ref decl, .. }) => {
36613737
// Only render when the method is not static or we allow static methods
36623738
if render_method_item {
36633739
let id = cx.derive_id(format!("{}.{}", item_type, name));
36643740
let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space()));
36653741
write!(w, "<h4 id='{}' class=\"{}{}\">", id, item_type, extra_class);
3742+
write!(w, "{}", spotlight_decl(decl));
36663743
write!(w, "<code id='{}'>", ns_id);
36673744
render_assoc_item(w, item, link.anchor(&id), ItemType::Impl);
36683745
write!(w, "</code>");

src/librustdoc/html/static/main.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,7 @@ function defocusSearchBar() {
363363
function handleEscape(ev) {
364364
var help = getHelpElement();
365365
var search = getSearchElement();
366+
hideModal();
366367
if (hasClass(help, "hidden") === false) {
367368
displayHelp(false, ev, help);
368369
} else if (hasClass(search, "hidden") === false) {
@@ -395,6 +396,7 @@ function defocusSearchBar() {
395396
case "s":
396397
case "S":
397398
displayHelp(false, ev);
399+
hideModal();
398400
ev.preventDefault();
399401
focusSearchBar();
400402
break;
@@ -407,6 +409,7 @@ function defocusSearchBar() {
407409

408410
case "?":
409411
if (ev.shiftKey) {
412+
hideModal();
410413
displayHelp(true, ev);
411414
}
412415
break;
@@ -2621,6 +2624,31 @@ function defocusSearchBar() {
26212624
});
26222625
}());
26232626

2627+
function showModal(content) {
2628+
var modal = document.createElement("div");
2629+
modal.id = "important";
2630+
addClass(modal, "modal");
2631+
modal.innerHTML = "<div class=\"modal-content\"><div class=\"close\" id=\"modal-close\">✕" +
2632+
"</div><div class=\"whiter\"></div><span class=\"docblock\">" + content +
2633+
"</span></div>";
2634+
document.getElementsByTagName("body")[0].appendChild(modal);
2635+
document.getElementById("modal-close").onclick = hideModal;
2636+
modal.onclick = hideModal;
2637+
}
2638+
2639+
function hideModal() {
2640+
var modal = document.getElementById("important");
2641+
if (modal) {
2642+
modal.parentNode.removeChild(modal);
2643+
}
2644+
}
2645+
2646+
onEachLazy(document.getElementsByClassName("important-traits"), function(e) {
2647+
e.onclick = function() {
2648+
showModal(e.lastElementChild.innerHTML);
2649+
};
2650+
});
2651+
26242652
// In the search display, allows to switch between tabs.
26252653
function printTab(nb) {
26262654
if (nb === 0 || nb === 1 || nb === 2) {

0 commit comments

Comments
 (0)