Skip to content

Commit 9845075

Browse files
committed
Revert "Remove "important traits" feature"
This reverts commit 1244ced.
1 parent 6ee1b62 commit 9845075

File tree

15 files changed

+393
-9
lines changed

15 files changed

+393
-9
lines changed

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

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

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

155176
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
@@ -995,6 +995,7 @@ pub struct Trait {
995995
pub items: Vec<Item>,
996996
pub generics: Generics,
997997
pub bounds: Vec<GenericBound>,
998+
pub is_spotlight: bool,
998999
pub is_auto: bool,
9991000
}
10001001

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: 82 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2410,7 +2410,7 @@ fn item_function(w: &mut Buffer, cx: &Context, it: &clean::Item, f: &clean::Func
24102410
f.generics.print()
24112411
)
24122412
.len();
2413-
write!(w, "<pre class='rust fn'>");
2413+
write!(w, "{}<pre class='rust fn'>", render_spotlight_traits(it));
24142414
render_attributes(w, it, false);
24152415
write!(
24162416
w,
@@ -2612,7 +2612,12 @@ fn item_trait(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Trait)
26122612
let name = m.name.as_ref().unwrap();
26132613
let item_type = m.type_();
26142614
let id = cx.derive_id(format!("{}.{}", item_type, name));
2615-
write!(w, "<h3 id='{id}' class='method'><code>", id = id);
2615+
write!(
2616+
w,
2617+
"<h3 id='{id}' class='method'>{extra}<code>",
2618+
extra = render_spotlight_traits(m),
2619+
id = id
2620+
);
26162621
render_assoc_item(w, m, AssocItemLink::Anchor(Some(&id)), ItemType::Impl);
26172622
write!(w, "</code>");
26182623
render_stability_since(w, m, t);
@@ -3559,6 +3564,76 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool) -> bool {
35593564
}
35603565
}
35613566

3567+
fn render_spotlight_traits(item: &clean::Item) -> String {
3568+
match item.inner {
3569+
clean::FunctionItem(clean::Function { ref decl, .. })
3570+
| clean::TyMethodItem(clean::TyMethod { ref decl, .. })
3571+
| clean::MethodItem(clean::Method { ref decl, .. })
3572+
| clean::ForeignFunctionItem(clean::Function { ref decl, .. }) => spotlight_decl(decl),
3573+
_ => String::new(),
3574+
}
3575+
}
3576+
3577+
fn spotlight_decl(decl: &clean::FnDecl) -> String {
3578+
let mut out = Buffer::html();
3579+
let mut trait_ = String::new();
3580+
3581+
if let Some(did) = decl.output.def_id() {
3582+
let c = cache();
3583+
if let Some(impls) = c.impls.get(&did) {
3584+
for i in impls {
3585+
let impl_ = i.inner_impl();
3586+
if impl_.trait_.def_id().map_or(false, |d| c.traits[&d].is_spotlight) {
3587+
if out.is_empty() {
3588+
out.push_str(&format!(
3589+
"<h3 class=\"important\">Important traits for {}</h3>\
3590+
<code class=\"content\">",
3591+
impl_.for_.print()
3592+
));
3593+
trait_.push_str(&impl_.for_.print().to_string());
3594+
}
3595+
3596+
//use the "where" class here to make it small
3597+
out.push_str(&format!(
3598+
"<span class=\"where fmt-newline\">{}</span>",
3599+
impl_.print()
3600+
));
3601+
let t_did = impl_.trait_.def_id().unwrap();
3602+
for it in &impl_.items {
3603+
if let clean::TypedefItem(ref tydef, _) = it.inner {
3604+
out.push_str("<span class=\"where fmt-newline\"> ");
3605+
assoc_type(
3606+
&mut out,
3607+
it,
3608+
&[],
3609+
Some(&tydef.type_),
3610+
AssocItemLink::GotoSource(t_did, &FxHashSet::default()),
3611+
"",
3612+
);
3613+
out.push_str(";</span>");
3614+
}
3615+
}
3616+
}
3617+
}
3618+
}
3619+
}
3620+
3621+
if !out.is_empty() {
3622+
out.insert_str(
3623+
0,
3624+
&format!(
3625+
"<div class=\"important-traits\"><div class='tooltip'>ⓘ\
3626+
<span class='tooltiptext'>Important traits for {}</span></div>\
3627+
<div class=\"content hidden\">",
3628+
trait_
3629+
),
3630+
);
3631+
out.push_str("</code></div></div>");
3632+
}
3633+
3634+
out.into_inner()
3635+
}
3636+
35623637
fn render_impl(
35633638
w: &mut Buffer,
35643639
cx: &Context,
@@ -3665,12 +3740,14 @@ fn render_impl(
36653740
(true, " hidden")
36663741
};
36673742
match item.inner {
3668-
clean::MethodItem(clean::Method { .. })
3669-
| clean::TyMethodItem(clean::TyMethod { .. }) => {
3743+
clean::MethodItem(clean::Method { ref decl, .. })
3744+
| clean::TyMethodItem(clean::TyMethod { ref decl, .. }) => {
36703745
// Only render when the method is not static or we allow static methods
36713746
if render_method_item {
36723747
let id = cx.derive_id(format!("{}.{}", item_type, name));
3673-
write!(w, "<h4 id='{}' class=\"{}{}\"><code>", id, item_type, extra_class);
3748+
write!(w, "<h4 id='{}' class=\"{}{}\">", id, item_type, extra_class);
3749+
write!(w, "{}", spotlight_decl(decl));
3750+
write!(w, "<code>");
36743751
render_assoc_item(w, item, link.anchor(&id), ItemType::Impl);
36753752
write!(w, "</code>");
36763753
render_stability_since_raw(w, item.stable_since(), outer_version);

src/librustdoc/html/static/main.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,7 @@ function defocusSearchBar() {
365365
function handleEscape(ev) {
366366
var help = getHelpElement();
367367
var search = getSearchElement();
368+
hideModal();
368369
if (hasClass(help, "hidden") === false) {
369370
displayHelp(false, ev, help);
370371
} else if (hasClass(search, "hidden") === false) {
@@ -397,6 +398,7 @@ function defocusSearchBar() {
397398
case "s":
398399
case "S":
399400
displayHelp(false, ev);
401+
hideModal();
400402
ev.preventDefault();
401403
focusSearchBar();
402404
break;
@@ -409,6 +411,7 @@ function defocusSearchBar() {
409411

410412
case "?":
411413
if (ev.shiftKey) {
414+
hideModal();
412415
displayHelp(true, ev);
413416
}
414417
break;
@@ -2636,6 +2639,31 @@ function defocusSearchBar() {
26362639
});
26372640
}());
26382641

2642+
function showModal(content) {
2643+
var modal = document.createElement("div");
2644+
modal.id = "important";
2645+
addClass(modal, "modal");
2646+
modal.innerHTML = "<div class=\"modal-content\"><div class=\"close\" id=\"modal-close\">✕" +
2647+
"</div><div class=\"whiter\"></div><span class=\"docblock\">" + content +
2648+
"</span></div>";
2649+
document.getElementsByTagName("body")[0].appendChild(modal);
2650+
document.getElementById("modal-close").onclick = hideModal;
2651+
modal.onclick = hideModal;
2652+
}
2653+
2654+
function hideModal() {
2655+
var modal = document.getElementById("important");
2656+
if (modal) {
2657+
modal.parentNode.removeChild(modal);
2658+
}
2659+
}
2660+
2661+
onEachLazy(document.getElementsByClassName("important-traits"), function(e) {
2662+
e.onclick = function() {
2663+
showModal(e.lastElementChild.innerHTML);
2664+
};
2665+
});
2666+
26392667
// In the search display, allows to switch between tabs.
26402668
function printTab(nb) {
26412669
if (nb === 0 || nb === 1 || nb === 2) {

0 commit comments

Comments
 (0)